Jackson:尝试将JSON反序列化为Java对象时,未解析的前向引用

时间:2019-04-06 14:29:48

标签: java json jackson deserialization json-deserialization

我在Jackson的问题上停留了很长时间,我很想解决这个问题。我有一个JSON,其中包含对象,这些对象彼此之间使用ID进行引用,因此我需要将其反序列化为对象,但是在尝试这样做时,我一直在获取Unresolved forward references exception

我已经尝试在上述类中使用Jackson注解@JsonIdentityInfo,但这没有产生任何结果。

JSON的示例:

{
  "customer": [
    {
      "id": 1,
      "name": "Jane Gallow",
      "age": 16
    },
    {
      "id": 2,
      "name": "John Sharp",
      "age": 20
    },
  ],
  "shoppingcart": [
    {
      "id": 1,
      "customer": 2,
      "orderDate": "2015-02-19"
    }
  ]
}

客户类别


@JsonIdentityInfo(generator= ObjectIdGenerators.PropertyGenerator.class, property="id",scope = Customer.class)
@JsonIdentityReference(alwaysAsId = true)
public class Customer {

    private int id = -1;

    private String name;

    private int age;

    //getters, setters
}

购物车类


<!-- language: java -->

@JsonIdentityInfo(generator= ObjectIdGenerators.PropertyGenerator.class, property="id",scope = ShoppingCart.class)
public class ShoppingCart {

    private int id = -1;

    private Customer customer;

    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    private LocalDate orderDate = LocalDate.now();

    //getters, setters
}

我希望Jackson给我一个ShoppinCart对象,该对象引用ID为Customer的{​​{1}}对象(在本例中为John Sharp)。但是当我尝试使用2方法从JSON读取数据时,它却无法工作,并且给了我"main" com.fasterxml.jackson.databind.deser.UnresolvedForwardReference

2 个答案:

答案 0 :(得分:0)

您应该在媒体资源上使用JsonIdentityReference

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = ShoppingCart.class)
class ShoppingCart {

    private int id = -1;

    @JsonIdentityReference
    private Customer customer;
    private LocalDate orderDate;

    // getters, setters, toString
}

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id", scope = Customer.class)
class Customer {

    private int id = -1;
    private String name;
    private int age;

    // getters, setters, toString
}

简单的例子:

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

import java.io.File;
import java.time.LocalDate;
import java.util.List;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        mapper.enable(SerializationFeature.INDENT_OUTPUT);

        System.out.println(mapper.readValue(jsonFile, Pojo.class));
    }
}

为您的JSON打印件:

Pojo{customers=[Customer{id=1, name='Jane Gallow', age=16}, Customer{id=2, name='John Sharp', age=20}], shoppingCarts=[ShoppingCart{id=1, customer=Customer{id=2, name='John Sharp', age=20}, orderDate=2015-02-19}]}

另请参阅:

答案 1 :(得分:0)

反序列化期间,我对未解决的前向引用有相同的问题。我使用了https://www.logicbig.com/tutorials/misc/jackson/json-identity-reference.html上提供的示例来检查并解决我的问题。 有一个非常简单的类:

public class Order {
  private int orderId;
  private List<Integer> itemIds;
  private Customer customer;
....
}

我在@Customer类中添加了@JsonCreator静态工厂方法,它没有引起任何问题。

现在,当我向Order类添加任何类型的@JsonCreator(静态方法或构造函数)时,我会立即获得未解决的前向引用。有趣的是,当我添加以下构造函数时,仅提供@JsonPropery批注:

 public Order(@JsonProperty("orderId") int orderId, @JsonProperty("itemIds") List<Integer> itemIds, @JsonProperty("customer") Customer customer) {
    this.orderId = orderId;
    this.itemIds = itemIds;
    this.customer = customer;
}

它还会导致未解决的前向引用。

要解决此问题,必须为Order类创建无参数构造函数(可以是私有的)。否则,您将得到:

  

线程“ main”中的异常com.fasterxml.jackson.databind.exc.InvalidDefinitionException:无法构造com.logicbig.example.Order的实例(不存在像默认构造一样的创建者):无法从Object值反序列化(没有委托-或基于资源的创作者)

,绝不能有任何@JsonCreator注释的方法和构造函数,或带有@JsonProperty注释的构造函数。

仅此而已。