Java 不可变/多态POJO<-&燃气轮机;Jackson的JSON序列化
我正在尝试使用Jackson 2.1.4在JSON之间序列化一个不可变的POJO,而不必编写自定义序列化程序,并且尽可能少地使用注释。我还希望避免仅仅为了满足Jackson库而添加不必要的getter或默认构造函数 我现在陷入了一个例外: JsonMappingException:找不到适合类型[simple type,class Circle]的构造函数:无法从JSON对象实例化(需要添加/启用类型信息?) 守则:Java 不可变/多态POJO<-&燃气轮机;Jackson的JSON序列化,java,json,inheritance,jackson,immutability,Java,Json,Inheritance,Jackson,Immutability,我正在尝试使用Jackson 2.1.4在JSON之间序列化一个不可变的POJO,而不必编写自定义序列化程序,并且尽可能少地使用注释。我还希望避免仅仅为了满足Jackson库而添加不必要的getter或默认构造函数 我现在陷入了一个例外: JsonMappingException:找不到适合类型[simple type,class Circle]的构造函数:无法从JSON对象实例化(需要添加/启用类型信息?) 守则: public abstract class Shape {} public
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);
非常感谢您的帮助,谢谢 矩形有两个参数,表示: 反序列化简单类型 如果我想反序列化简单的JSON值(字符串、整数/ 十进制数)转换为默认支持以外的类型,是否需要 要编写自定义反序列化程序 不一定。如果要反序列化到的类具有以下之一:
- 具有匹配类型(字符串、int/double)的单参数构造函数,或
- 名为“valueOf()”且参数类型匹配的单参数静态方法
@JsonSubTypes({@JsonSubTypes.Type(Circle.class), @JsonSubTypes.Type(Rectangle.class)})
public abstract class Shape {}
看看这个库吧,它的一些关键特性正好解决了您的问题:多态性,不需要注释和最重要的不可变POJO。在您的示例中,所有内容都使用0注释或重配置
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还为您提供了使用别名(而不是使用类名)的功能
看起来很有希望,但现在我得到了以下异常:JsonMappingException:constructor[constructor for Circle,annotations:{interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator()}的参数#0没有属性名注释;当存在@JsonProperty注释时,多个参数构造函数注释为creator时必须具有名称?是的,如示例中所示。在所有构造函数参数上。是的-你是对的!这些类是嵌套的(在我的测试用例中),需要“静态”才能工作!所以,现在一切都很顺利!有趣的是,它不需要JsonCreator或JsonSubTypes来工作。唯一需要的注释是JsonProperty!谢谢当您认为非静态内部类具有“隐藏”的第一个参数时,就可以将这个“指针”传递给父类。这是编译器诱导的语法糖,允许非静态内部类引用封闭父类实例的实例字段。
@JsonSubTypes({@JsonSubTypes.Type(Circle.class), @JsonSubTypes.Type(Rectangle.class)})
public abstract class Shape {}
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);
new Genson.Builder().addAlias("shape", Shape.class)
.addAlias("circle", Circle.class)
.create();