JSON-Bは、ポリモーフィック型のシリアライズの標準的な方法を宣言しません:-)大歓迎助けます。しかし、カスタムシリアライザとデシリアライザを使用して手動で達成できます。簡単なサンプルで説明します。
Shape
インターフェイスと2つのクラスSquare
とCircle
が実装されているとします。
public interface Shape {
double surface();
double perimeter();
}
public static class Square implements Shape {
private double side;
public Square() {
}
public Square(double side) {
this.side = side;
}
public double getSide() {
return side;
}
public void setSide(double side) {
this.side = side;
}
@Override
public String toString() {
return String.format("Square[side=%s]", side);
}
@Override
public double surface() {
return side * side;
}
@Override
public double perimeter() {
return 4 * side;
}
}
public static class Circle implements Shape {
private double radius;
public Circle() {
}
public Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
@Override
public String toString() {
return String.format("Circle[radius=%s]", radius);
}
@Override
public double surface() {
return Math.PI * radius * radius;
}
@Override
public double perimeter() {
return 2 * Math.PI * radius;
}
}
Shape
の実装を含むListを直列化および逆直列化する必要があります。
シリアル化は、箱から出して動作します:
JsonbConfig config = new JsonbConfig().withFormatting(true);
Jsonb jsonb = JsonbBuilder.create(config);
// Create a sample list
List<SerializerSample.Shape> shapes = Arrays.asList(
new SerializerSample.Square(2),
new SerializerSample.Circle(5));
// Serialize
String json = jsonb.toJson(shapes);
System.out.println(json);
結果は以下のようになります。
[
{
"side": 2.0
},
{
"radius": 5.0
}
]
それは大丈夫ですが、あなたがそれをデシリアライズしようとした場合、それは動作しません。逆シリアル化中に、JSON-BはSquare
またはCircle
のインスタンスを作成する必要があり、JSONドキュメントのオブジェクトタイプに関する情報はありません。
これを修正するには、この情報を手動で追加する必要があります。ここでシリアライザとデシリアライザが役に立ちます。シリアライザを作成して、シリアライズされたオブジェクトをJSONドキュメントに配置し、デシリアライザを使用してそれを読み込んで適切なインスタンスを作成します。
これでJSON-Bエンジンに接続してシリアル化を試す必要があります。シリアライズ/デシリアライズ時にジェネリック型をJSON-Bエンジンに渡すことを忘れないでください。それ以外の場合は正しく動作しません。
// Create JSONB engine with pretty output and custom serializer/deserializer
JsonbConfig config = new JsonbConfig()
.withFormatting(true)
.withSerializers(new SerializerSample.ShapeSerializer())
.withDeserializers(new SerializerSample.ShapeDeserializer());
Jsonb jsonb = JsonbBuilder.create(config);
// Create a sample list
List<SerializerSample.Shape> shapes = Arrays.asList(
new SerializerSample.Square(2),
new SerializerSample.Circle(5));
// Type of our list
Type type = new ArrayList<SerializerSample.Shape>() {}.getClass().getGenericSuperclass();
// Serialize
System.out.println("Serialization:");
String json = jsonb.toJson(shapes);
System.out.println(json);
シリアライズの結果は以下のようになります。
[
{
"jsonb.sample.SerializerSample$Square": {
"side": 2.0
}
},
{
"jsonb.sample.SerializerSample$Circle": {
"radius": 5.0
}
}
]
あなたがオブジェクト型がShapeSerializer
によって追加されたことがわかります。今度はそれとプリント結果をデシリアライズしてみましょう:
// Deserialize
List<SerializerSample.Shape> deserializedShapes = jsonb.fromJson(json, type);
// Print results
System.out.println("Deserialization:");
for (SerializerSample.Shape shape : deserializedShapes) {
System.out.println(shape);
}
結果は次のとおりです。
Square[side=2.0]
Circle[radius=5.0]
だから、それは完璧に動作します。それが役に立てば幸い。 :)
私はYassonで[pullrequest](https://github.com/eclipse/yasson/pull/64)を作成しました。これはこの問題に対処する必要があります。 ImplementationClassTestの使用法を見て、コメントすることができます。 – Bravehorsie