JSPON仕様に従って参照を処理できるJavaJSPONシリアライザーを探しています。
現在これを行うことができる利用可能なものはありますか?または、既存のシリアライザーを変更して、$ ref表記のオブジェクト参照を処理する方法はありますか?
JSPON仕様に従って参照を処理できるJavaJSPONシリアライザーを探しています。
現在これを行うことができる利用可能なものはありますか?または、既存のシリアライザーを変更して、$ ref表記のオブジェクト参照を処理する方法はありますか?
注: 私はEclipseLink JAXB(MOXy)のリーダーであり、JAXB 2(JSR-222)エキスパートグループのメンバーです。
オブジェクト-JSONバインディングのアプローチに興味がある場合は、MOXyを使用してどのように実行できるかを以下に示します。以下の例は、JSPONコア仕様の例に基づいています。
親
Parent
クラスは、JSONメッセージのルートに対応するドメインオブジェクトです。タイプが2つのフィールドがありChild
ます。
package forum9862100;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class Parent {
protected Child field1;
protected Child field2;
}
子
Child
クラスはそのキーによって参照される場合があります。このユースケースは。で処理しますXmlAdapter
。アノテーションXmlAdapter
を介してリンクします。@XmlJavaTypeAdapter
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;
}
ChildAdapter
以下はの実装ですXmlAdapter
。これはステートフルです。つまり、とXmlAdapter
にインスタンスを設定する必要があります。Marshaller
Unmarshaller
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;
}
}
デモ
XmlAdapter
以下のコードは、Marshaller
およびUnmarshaller
:でステートフルを指定する方法を示しています。
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);
}
}
出力
以下は、デモコードの実行からの出力です。の2つのインスタンスがどのようにChild
IDテストに合格するかに注意してください。
true
{
"field1" : {
"id" : "2",
"foo" : "val",
"bar" : 4
},
"field2" : {
"$ref" : "2"
}}
詳細については
ObjecttoJSonシリアル化ライブラリの多くの1つを使用します。ライブラリの多くは拡張可能ですが、これらをいつ使用するかについて実用的な選択をしない限り、参照の追加は複雑になる可能性があると思います。