【问题标题】:JAXB Unmarshal JSON HTTP POST ParametersJAXB 解组 JSON HTTP POST 参数
【发布时间】:2018-08-24 23:47:22
【问题描述】:

我试图在 POST 请求中从 JSON 中提取参数。这似乎是一个非常基本的过程,我已经阅读了很多关于此的帖子,但我在这里遗漏了一些东西,因为我正在取回一个对象,但该对象中的字段为空。在我的 POST 中,我有以下 JSON...

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

这是我的 servlet 中的 POST 方法...

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);
    }
}

最后,这是我的 ClientAndTopicParameters 类...

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

结果输出如下...

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

如您所见,这是非常基本的东西。我假设我错过了一些我只是没有看到的小东西。欢迎任何想法和见解。作为参考,我使用的是 JAXB v2.3.0

【问题讨论】:

  • JAXB 用于编组/解组 XML 文件,而不是用于读取 JSON 内容。你应该使用 Jackson、Gson 或其他东西来阅读你的 pojo。 Here 您可以在签入您想用来解析请求正文的正确技术后生成您的 pojo,使用此生成的 POJO,您的 JSON 肯定会被 Jackson/Gson 读取。
  • 我不确定这是否正确 m4gic。我正在使用 JAXB 为我的其他对象编组和解组 JSON。因此 unmarshal.setProperty (UnmarshallerProperties.MEDIA_TYPE, "application/json");唯一的区别是在这种情况下我没有指定 XMLRoolElement。通常我有@XmlRoolElement (name="MyObject")。但在这种情况下,这里的 JSON 是对象,而不是 JSON 中指定的对象。例如... {"MyObject":{JSON DATA...}}。相反,我有 {JSON DATA...}。所以我猜我正在寻找如何指定此 JSON 用于我的对象 ClientAndTopicParameters。
  • 嗨,是的,我不知道jaxb can handle this。因此,如果您使用一些额外的技术,例如 Jackson 或 Moxy,似乎可以使用 JAXB 编组/解组 JSON ......这些额外的技术可以自己处理 JSON,对我来说,单独使用 Jackson 会更清楚(作为本机JSON解析器/序列化器)比以这种方式使用JAXB。我认为杰克逊在这方面要好得多。使用 XML 注释来注释 POJO 以进行 JSON 处理对我来说是令人困惑的。
  • 您应该在问题中添加您使用的是什么 jaxb 版本,这将有助于重现您的问题。
  • 谢谢@m4gic。好点,我会添加版本。另外,我选择了 JAXB,以便它处理我正在使用的 JPA 实体。我承认虽然我没有研究过杰克逊。我一定会看看的。

标签: java http post jaxb


【解决方案1】:

解决方案是序列化您想要的对象并使用 includeRoot 标志。如果将其设置为 false,您将获得所需的输出。

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);
    }
}

我使用了这些依赖项:

        <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>

在您的代码中,这是您唯一需要更改的内容:

unmarshal.setProperty (UnmarshallerProperties.JSON_INCLUDE_ROOT, false);

【讨论】:

  • 你也要设置eclipselink的jaxb context factory...
  • 再次感谢@m4gic。这就是解决方案。我知道这一定很简单。我实际上只是尝试注释掉我将 JSON_INCLUDE_ROOT 设置为 true 的那一行。计算它会默认为假。看来这需要明确设置。简单的改变,一切都有效。再次感谢您的所有帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-24
  • 2011-01-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多