我正在尝试使用Jackson 2.1.4将不可变POJO与JSON序列化,而不必编写自定义序列化程序并尽可能少注释。我还想避免为了满足杰克逊图书馆而添加不必要的getter或默认构造函数。
我现在坚持异常:
JsonMappingException:找不到类型[simple type,class Circle]的合适构造函数:无法从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);
非常感谢任何帮助,谢谢!
答案 0 :(得分:10)
您可以(根据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;
}
}
编辑:也许您必须使用@JsonSubTypes注释Shape类,以便确定Shape的具体子类。
@JsonSubTypes({@JsonSubTypes.Type(Circle.class), @JsonSubTypes.Type(Rectangle.class)})
public abstract class Shape {}
答案 1 :(得分:3)
查看Genson库的一些主要功能是解决您的确切问题:多态,不需要注释和最重要的不可变pojos。一切都在你的例子中有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();
答案 2 :(得分:1)
Rectangle有两个参数,FAQ表示:
反序列化简单类型
如果我想反序列化简单的JSON值(字符串,整数/ 十进制数字)到默认支持以外的类型,我需要 编写自定义反序列化程序?
不一定。如果要反序列化的类具有以下之一:
- 具有匹配类型(String,int / double)或
的单参数构造函数- 单参数静态方法,名称为“valueOf()”,匹配参数类型为
杰克逊将使用这种方法,将匹配的JSON值传递为 参数。
我担心你必须自己编写deserializer as show in the Jackson documentation:
ObjectMapper mapper = new ObjectMapper();
SimpleModule testModule =
new SimpleModule("MyModule", new Version(1, 0, 0, null))
.addDeserializer( MyType.class, new MyTypeDeserializer());
mapper.registerModule( testModule );