不可改变/多态性POJO < - > JSON序列与杰克逊(Immutable/poly

2019-08-17 04:55发布

我试图序列化不可改变的POJO,并从JSON,使用杰克逊2.1.4,而无需编写自定义序列,并用尽可能少的注释越好。 我也很喜欢,以避免增加不必要的getter或默认构造正好满足了杰克逊库。

现在我卡除外上:

JsonMappingException:找到类型没有合适的构造[简单类型,类圆]:不能从JSON对象实例化(需要添加/启用类型信息?)

代码:

public abstract class Shape {}


public class Circle extends Shape {
  public final int radius; // Immutable - no getter needed

  public Circle(int radius) {
    this.radius = radius;
  }
}


public class Rectangle extends Shape {
  public final int w; // Immutable - no getter needed
  public final int h; // Immutable - no getter needed

  public Rectangle(int w, int h) {
    this.w = w;
    this.h = h;
  }
}

测试代码:

ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); // Adds type info

Shape circle = new Circle(10);
Shape rectangle = new Rectangle(20, 30);

String jsonCircle = mapper.writeValueAsString(circle);
String jsonRectangle = mapper.writeValueAsString(rectangle);

System.out.println(jsonCircle); // {"@class":"Circle","radius":123}
System.out.println(jsonRectangle); // {"@class":"Rectangle","w":20,"h":30}

// Throws:
//  JsonMappingException: No suitable constructor found.
//  Can not instantiate from JSON object (need to add/enable type information?)
Shape newCircle = mapper.readValue(jsonCircle, Shape.class);
Shape newRectangle = mapper.readValue(jsonRectangle, Shape.class);

System.out.println("newCircle = " + newCircle);
System.out.println("newRectangle = " + newRectangle);

任何帮助非常感谢,谢谢!

Answer 1:

你可以(根据API)注释与构造@JsonCreator并与参数@JsonProperty 。

public class Circle extends Shape {
    public final int radius; // Immutable - no getter needed

    @JsonCreator
    public Circle(@JsonProperty("radius") int radius) {
        this.radius = radius;
    }
}

public class Rectangle extends Shape {
    public final int w; // Immutable - no getter needed
    public final int h; // Immutable - no getter needed

    @JsonCreator        
    public Rectangle(@JsonProperty("w") int w, @JsonProperty("h") int h) {
        this.w = w;
        this.h = h;
    }
}

编辑:也许你有注释Shape类@JsonSubTypes使形状的具体子类可以被确定。

@JsonSubTypes({@JsonSubTypes.Type(Circle.class), @JsonSubTypes.Type(Rectangle.class)})
public abstract class Shape {}


Answer 2:

看看Genson库它的一些主要特性adressing您的具体问题:多态,不需要注解和最重要的不变的POJO。 一切正常,分别以0注释或重的conf你的榜样。

Genson genson = new Genson.Builder().setWithClassMetadata(true)
                            .setWithDebugInfoPropertyNameResolver(true)
                            .create();

String jsonCircle = genson.serialize(circle);
String jsonRectangle = genson.serialize(rectangle);

System.out.println(jsonCircle); // {"@class":"your.package.Circle","radius":123}
System.out.println(jsonRectangle); // {"@class":"your.package.Rectangle","w":20,"h":30}

// Throws nothing :)
Shape newCircle = genson.deserialize(jsonCircle, Shape.class);
Shape newRectangle = genson.deserialize(jsonRectangle, Shape.class);

Genson给你也使用别名(代替类名)的能力。

new Genson.Builder().addAlias("shape", Shape.class)
                .addAlias("circle", Circle.class)
                .create();


Answer 3:

矩形有两个参数,和常见问题解答说:

反序列化简单类型

如果我想不是默认支持的反序列化简单的JSON值(字符串,整数/十进制数)转换成其他类型的,我需要写一个自定义解串器?

不必要。 如果类反序列化成了之一:

  • 单个参数的构造与匹配的类型(字符串,整数/双),或
  • 名为“的valueOf()”,和匹配参数类型单参数静态方法

杰克逊将使用这样的方法,传入JSON值匹配作为参数。

恐怕你必须写自己的解串器作为表演杰克逊文件中 :

ObjectMapper mapper = new ObjectMapper();
SimpleModule testModule =
   new SimpleModule("MyModule", new Version(1, 0, 0, null))
      .addDeserializer( MyType.class, new MyTypeDeserializer());
mapper.registerModule( testModule );


文章来源: Immutable/polymorphic POJO <-> JSON serialization with Jackson