Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 不可变/多态POJO<-&燃气轮机;Jackson的JSON序列化_Java_Json_Inheritance_Jackson_Immutability - Fatal编程技术网

Java 不可变/多态POJO<-&燃气轮机;Jackson的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

我正在尝试使用Jackson 2.1.4在JSON之间序列化一个不可变的POJO,而不必编写自定义序列化程序,并且尽可能少地使用注释。我还希望避免仅仅为了满足Jackson库而添加不必要的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);

非常感谢您的帮助,谢谢

矩形有两个参数,表示:

反序列化简单类型

如果我想反序列化简单的JSON值(字符串、整数/ 十进制数)转换为默认支持以外的类型,是否需要 要编写自定义反序列化程序

不一定。如果要反序列化到的类具有以下之一:

  • 具有匹配类型(字符串、int/double)的单参数构造函数,或
  • 名为“valueOf()”且参数类型匹配的单参数静态方法
Jackson将使用这种方法,将匹配的JSON值作为 争论

恐怕你得自己写:

您可以(根据API)使用注释构造函数,使用注释参数

编辑:也许您必须用注释Shape类,以便确定Shape的具体子类

@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();