【问题标题】:Is there any Java support for JSPON serialization with references?是否有对带有引用的 JSPON 序列化的 Java 支持?
【发布时间】:2012-03-25 16:59:11
【问题描述】:

我正在寻找可以根据JSPON specification.处理引用的Java JSPON序列化程序

目前有没有可以做到这一点的?或者有什么方法可以修改现有的序列化程序以使用 $ref 表示法处理对象引用?

【问题讨论】:

    标签: java json jsonserializer


    【解决方案1】:

    注意:我是EclipseLink JAXB (MOXy) 领导,也是JAXB 2 (JSR-222) 专家组的成员。

    如果您对对象-JSON 绑定方法感兴趣,以下是如何使用 MOXy 完成的。以下示例基于 JSPON 核心规范中的示例一:

    家长

    Parent 类是对应于 JSON 消息根的域对象。它有两个类型为Child 的字段。

    package forum9862100;
    
    import javax.xml.bind.annotation.*;
    
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Parent {
    
        protected Child field1;
        protected Child field2;
    
    }
    

    儿童

    Child 类可以通过它的键来引用。我们将使用XmlAdapter 处理这个用例。我们通过@XmlJavaTypeAdapter 注解链接到XmlAdapter

    package forum9862100;
    
    import javax.xml.bind.annotation.*;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    
    @XmlJavaTypeAdapter(ChildAdapter.class)
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Child {
    
        protected String id;
        protected String foo;
        protected Integer bar;
    
    }
    

    子适配器

    下面是XmlAdapter 的实现。这个XmlAdapter 是有状态的,这意味着我们需要在MarshallerUnmarshaller 上设置一个实例。

    package forum9862100;
    
    import java.util.*;
    
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.adapters.XmlAdapter;
    
    public class ChildAdapter extends XmlAdapter<ChildAdapter.AdaptedChild, Child>{
    
        private List<Child> childList = new ArrayList<Child>();
        private Map<String, Child> childMap = new HashMap<String, Child>();
    
        public static class AdaptedChild extends Child {
            @XmlElement(name="$ref")
            public String reference;
        }
    
        @Override
        public AdaptedChild marshal(Child child) throws Exception {
            AdaptedChild adaptedChild = new AdaptedChild();
            if(childList.contains(child)) {
                adaptedChild.reference = child.id;
            } else {
                adaptedChild.id = child.id;
                adaptedChild.foo = child.foo;
                adaptedChild.bar = child.bar;
                childList.add(child);
            }
            return adaptedChild;
        }
    
        @Override
        public Child unmarshal(AdaptedChild adaptedChild) throws Exception {
            Child child = childMap.get(adaptedChild.reference);
            if(null == child) {
                child = new Child();
                child.id = adaptedChild.id;
                child.foo = adaptedChild.foo;
                child.bar = adaptedChild.bar;
                childMap.put(child.id, child);
            }
            return child;
        }
    
    }
    

    演示

    下面的代码演示了如何在MarshallerUnmarshaller 上指定有状态的XmlAdapter

    package forum9862100;
    
    import java.io.File;
    import javax.xml.bind.*;
    import javax.xml.transform.stream.StreamSource;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(Parent.class);
    
            StreamSource json = new StreamSource(new File("src/forum9862100/input.json"));
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            unmarshaller.setProperty("eclipselink.media-type", "application/json");
            unmarshaller.setProperty("eclipselink.json.include-root", false);
            unmarshaller.setAdapter(new ChildAdapter());
            Parent parent = (Parent) unmarshaller.unmarshal(json, Parent.class).getValue();
    
            System.out.println(parent.field1 == parent.field2);
    
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.setProperty("eclipselink.media-type", "application/json");
            marshaller.setProperty("eclipselink.json.include-root", false);
            marshaller.setAdapter(new ChildAdapter());
            marshaller.marshal(parent, System.out);
        }
    
    }
    

    输出

    下面是运行演示代码的输出。注意Child 的两个实例如何通过身份测试。

    true
    {
       "field1" : {
          "id" : "2",
          "foo" : "val",
          "bar" : 4
       },
       "field2" : {
          "$ref" : "2"
       }}
    

    更多信息

    【讨论】:

      【解决方案2】:

      我会使用众多 Object to JSON 序列化库之一。许多库都是可扩展的,但我怀疑添加引用可能会变得复杂,除非您就何时使用它们做出一些务实的选择。

      【讨论】:

        猜你喜欢
        • 2011-09-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-22
        • 1970-01-01
        • 2014-04-16
        相关资源
        最近更新 更多