【问题标题】:Unmarshalling array of complex JSON objects with MOXy JAXB 2.5.1使用 MOXy JAXB 2.5.1 解组复杂 JSON 对象数组
【发布时间】:2013-11-18 19:51:57
【问题描述】:

我正在尝试使用 MOXy JAXB 在 Apache CFX 项目中解组一些 JSON/XML。以下请求给我带来了麻烦:

{"CC.ConsumerPersistAppDataRequest" : {
    "SessionId" : "42",
    "AppData" : [
    {"AppDatum" : {
        "TimeStamp" : 1384548486,
        "Value" : "Some kind of String would go here"}},
    {"AppDatum" : {
        "TimeStamp" : 1384548578,
        "Value" : "I hope I am understanding this format correctly!"}},
    {"AppDatum" : {
        "TimeStamp" : 1384549696,
        "Value" : "One more time for the road..."}}],
    "MetaDataTags" : ["dumb", "dummy", "data"]}
}

在这里,AppData 被解组为 List,但是该列表仅包含最后一个元素。值得注意的是,“MetaDataTags”元素被正确解组为大小为 3 的 List

令人惊讶的是,尽管“AppData”应该期望 List (我不禁觉得这是相关的),但可以提交以下请求并获得相同的结果:

{"CC.ConsumerPersistAppDataRequest" : {
    "SessionId" : "42",
    "AppData" : {
        "AppDatum" : {
            "TimeStamp" : 1384548486,
            "Value" : "Some kind of String would go here"
        }
    }
}}

这个 XML 等价物(或我认为是 XML 等价物)按预期解析:

<?xml version="1.0" encoding="UTF-8"?>
<cc:ConsumerPersistAppDataRequest xmlns:cc="http://org/alg/ari/pnd/introspect/webservices/consumercomms">
   <SessionId>42</SessionId>
   <AppData>
      <AppDatum>
         <TimeStamp>1384548486</TimeStamp>
         <Value>Some kind of String would go here</Value>
      </AppDatum>
      <AppDatum>
        <TimeStamp>1384548578</TimeStamp>
        <Value>I hope I am understanding this format correctly!</Value>
      </AppDatum>
      <AppDatum>
        <TimeStamp>1384549696</TimeStamp>
        <Value>One more time for the road...</Value>
      </AppDatum>
   </AppData>
   <MetaDataTags>dumb dummy data</MetaDataTags>
</cc:ConsumerPersistAppDataRequest>

有问题的 JAXB 类(由 XJC 生成,cmets 省略):

package org.alg.ari.pnd.introspect.webservices.consumercomms;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlList;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "sessionId",
    "appData",
    "metaDataTags"
})
@XmlRootElement(name = "ConsumerPersistAppDataRequest")
public class ConsumerPersistAppDataRequest {

    @XmlElement(name = "SessionId", required = true)
    protected String sessionId;
    @XmlElement(name = "AppData", required = true)
    protected ConsumerPersistAppDataRequest.AppData appData;
    @XmlList
    @XmlElement(name = "MetaDataTags", required = true)
    protected List<String> metaDataTags;

    public String getSessionId() {
        return sessionId;
    }

    public void setSessionId(String value) {
        this.sessionId = value;
    }

    public ConsumerPersistAppDataRequest.AppData getAppData() {
        return appData;
    }

    public void setAppData(ConsumerPersistAppDataRequest.AppData value) {
        this.appData = value;
    }

    public List<String> getMetaDataTags() {
        if (metaDataTags == null) {
            metaDataTags = new ArrayList<String>();
        }
        return this.metaDataTags;
    }


    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "appDatum"
    })
    public static class AppData {

        @XmlElement(name = "AppDatum", required = true)
        protected List<ConsumerPersistAppDataRequest.AppData.AppDatum> appDatum;

        public List<ConsumerPersistAppDataRequest.AppData.AppDatum> getAppDatum() {
            if (appDatum == null) {
                appDatum = new ArrayList<ConsumerPersistAppDataRequest.AppData.AppDatum>();
            }
            return this.appDatum;
        }


        @XmlAccessorType(XmlAccessType.FIELD)
        @XmlType(name = "", propOrder = {
            "timeStamp",
            "value"
        })
        public static class AppDatum {

            @XmlElement(name = "TimeStamp")
            protected long timeStamp;
            @XmlElement(name = "Value", required = true)
            protected String value;

            public long getTimeStamp() {
                return timeStamp;
            }

            public void setTimeStamp(long value) {
                this.timeStamp = value;
            }

            public String getValue() {
                return value;
            }

            public void setValue(String value) {
                this.value = value;
            }
        }
    }
}

还有我的 MoxyJsonProvider bean

  <bean id="moxy-json-provider"
    class="org.eclipse.persistence.jaxb.rs.MOXyJsonProvider">
    <property name="attributePrefix" value="@" />
    <property name="formattedOutput" value="true" /> <!-- set to false for production! -->
    <property name="includeRoot" value="true" />
    <property name="marshalEmptyCollections" value="false" />
    <property name="valueWrapper" value="$" />
    <property name="namespacePrefixMapper" ref="json-ns-mapper" />
  </bean>

知道是什么导致了这个问题吗?这是 MOXy 2.5.1 版本中的错误吗?还是我需要在某个地方设置“开关”?

【问题讨论】:

    标签: json jaxb moxy


    【解决方案1】:

    根据您的映射,以下将是预期的 JSON 文档:

    {
       "CC.ConsumerPersistAppDataRequest" : {
          "SessionId" : "42",
          "AppData" : {
             "AppDatum" : [ {
                "TimeStamp" : 1384548486,
                "Value" : "Some kind of String would go here"
             }, {
                "TimeStamp" : 1384548578,
                "Value" : "I hope I am understanding this format correctly!"
             }, {
                "TimeStamp" : 1384549696,
                "Value" : "One more time for the road..."
             } ]
          },
          "MetaDataTags" : "dumb dummy data"
       }
    }
    

    以下是我根据你写的独立示例,用于读取 XML 并输出相应的 JSON:

    import java.io.File;
    import java.util.*;
    import javax.xml.bind.*;
    import org.eclipse.persistence.jaxb.MarshallerProperties;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(ConsumerPersistAppDataRequest.class);
    
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            File xml = new File("src/forum20056524/input.xml");
            ConsumerPersistAppDataRequest result = (ConsumerPersistAppDataRequest) unmarshaller.unmarshal(xml);
    
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
            marshaller.setProperty(MarshallerProperties.JSON_ATTRIBUTE_PREFIX, "@");
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, true);
            marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, false);
            marshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, "$");
            Map<String, String> jsonNsMapper = new HashMap<String, String>(1);
            jsonNsMapper.put("http://org/alg/ari/pnd/introspect/webservices/consumercomms", "CC");
            marshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, jsonNsMapper);
            marshaller.marshal(result, System.out);
        }
    
    }
    

    【讨论】:

    • 做到了!无法相信周转时间顺便说一句!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-25
    • 1970-01-01
    相关资源
    最近更新 更多