java - Java 是否支持带引用的 JSON 序列化?

标签 java json jsonserializer

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

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

最佳答案

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

如果您对对象-JSON 绑定(bind)方法感兴趣,下面是如何使用 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

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

了解更多信息

关于java - Java 是否支持带引用的 JSON 序列化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9862100/

相关文章:

java - 如何获取给定行号的所有 JDT AST 语句?

java - 使用 Java 在 Jackson 中进行通用对象序列化

python - 在 Python 2.6 中加载时维护 JSON 文件的键顺序

c# - 我怎样才能 "un-JsonIgnore"派生类中的属性?

java - Java 应用程序接收传入电子邮件的最简单方法是什么?

java - 我不确定什么是不正确的

java - xpage添加文件下载控件时出现AbstractMethodError

python - 将 JSONL 键与 JSON 展开为列

python - 序列化和反序列化用户定义类中的对象

javascript - 如何将日期字符串转换为没有时区的日期对象