JAXB Unmarshal JSON HTTP POST Parameters

2019-08-25 15:56发布

I'm attempted to pull parameters from JSON in a POST request. This seems like a very basic process and I've read through numerous posts about this but I'm missing something here as I'm getting an object back but the fields within that object are null. In my POST I have the following JSON...

{
  "client": "1",
  "forTopic": "topic"
}

And here is my POST method inside my servlet...

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
{           
    String requestBody = RESTUtil.getRequestBody (request);
    log.debug (requestBody);

    try
    {
        JAXBContext context = JAXBContext.newInstance (ClientAndTopicParameters.class);

        Unmarshaller unmarshal = context.createUnmarshaller ();

        unmarshal.setProperty (UnmarshallerProperties.MEDIA_TYPE, "application/json");
        unmarshal.setProperty (UnmarshallerProperties.JSON_INCLUDE_ROOT, true);

        ClientAndTopicParameters params = (ClientAndTopicParameters) unmarshal.unmarshal (new StreamSource (new StringReader (requestBody)), ClientAndTopicParameters.class).getValue ();

        log.debug ("params = " + params);
        log.debug ("client = " + params.client);
        log.debug ("forTopic = " + params.forTopic);
    }
    catch (JAXBException e)
    {
        log.error ("Unable to get Client and Topic parameters from POST.", e);
    }
}

Finally, here is my ClientAndTopicParameters class...

@XmlRootElement
public class ClientAndTopicParameters
{
    @XmlElement public String                       client;
    @XmlElement public String                       forTopic;
}

The resulting output is the following...

2018 Aug 24 17:44:55,806 DEBUG [MyServlet                        ] params = mypackage.ClientAndTopicParameters@2995a298
2018 Aug 24 17:44:55,806 DEBUG [MyServlet                        ] client = null
2018 Aug 24 17:44:55,806 DEBUG [MyServlet                        ] forTopic = null

As you can see this pretty basic stuff. I'm assuming I'm missing something small that I'm just not seeing. Welcome any thoughts and insights. For reference I'm using JAXB v2.3.0

1条回答
闹够了就滚
2楼-- · 2019-08-25 16:45

The solution is to serialize your desired object and play with the includeRoot flag. If you set it to false, you will get the desired output.

import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.jaxb.UnmarshallerProperties;

@XmlRootElement
public class ClientAndTopicParameters
{

    @XmlElement public String                       client;
    @XmlElement public String                       forTopic;


    public static void main(String[] args) {

        try
        {
            boolean includeRoot = true;

            JAXBContext context = JAXBContext.newInstance     (ClientAndTopicParameters.class);
            Unmarshaller unmarshal = context.createUnmarshaller ();
            unmarshal.setProperty (UnmarshallerProperties.MEDIA_TYPE,     "application/json");
            unmarshal.setProperty (UnmarshallerProperties.JSON_INCLUDE_ROOT,     includeRoot);

            parseAndPrint(unmarshal, "{ \"client\": \"1\",  \"forTopic\": \"topic\"}");
            StringWriter sw = marshallDesiredObject(context, includeRoot);
            parseAndPrint(unmarshal, sw.toString());
        }
        catch (JAXBException e)
        {
            System.out.println("Unable to get Client and Topic parameters from POST.");
            e.printStackTrace();
        }
    }

    private static StringWriter marshallDesiredObject(JAXBContext context, boolean includeRoot)
        throws JAXBException, PropertyException {
        Marshaller marshal = context.createMarshaller ();

        marshal.setProperty (UnmarshallerProperties.MEDIA_TYPE, "application/json");
        marshal.setProperty (UnmarshallerProperties.JSON_INCLUDE_ROOT, includeRoot);

        ClientAndTopicParameters cp = new ClientAndTopicParameters();
        cp.client = "1";
        cp.forTopic = "topic";

        StringWriter sw = new StringWriter();
        marshal.marshal(cp, sw);
        return sw;
    }

    private static void parseAndPrint(Unmarshaller unmarshal, String requestBody)
            throws JAXBException {
        System.out.println("requestBody to parse: " + requestBody);
        ClientAndTopicParameters params = unmarshal.unmarshal(new StreamSource (new     StringReader (requestBody )), ClientAndTopicParameters.class).getValue ();
        System.out.println("params = " + params);
        System.out.println("client = " + params.client);
        System.out.println("forTopic = " + params.forTopic);
    }
}

I used these dependencies:

        <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>org.eclipse.persistence.moxy</artifactId>
        <version>2.5.2</version>
    </dependency>
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.2.11</version>
    </dependency>

In your code, this is the only thing you have to change:

unmarshal.setProperty (UnmarshallerProperties.JSON_INCLUDE_ROOT, false);
查看更多
登录 后发表回答