Jackson:尝试将 JSON 反序列化为 java 对象时未解析的前向引用
Jackson: Unresolved forward references when trying to deserialize JSON into java objects
我已经被 Jackson
的问题困扰了很长一段时间,我很想解决它。我有一个 JSON
,其中包含使用 ID 相互引用的对象,我需要将其反序列化为对象,但我在尝试这样做时一直得到 Unresolved forward references exception
。
我已经尝试使用上述 class 中的 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"
}
]
}
客户class
@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
}
购物车class
<!-- 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
对象,它引用了 Customer
对象,id 为 2
(在本例中是 John Sharp) .但我无法让它工作,当我尝试使用 ObjectMapper.readValue()
方法从 JSON 读取时,它给了我 "main" com.fasterxml.jackson.databind.deser.UnresolvedForwardReference
。
您应该在 属性 上使用 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}]}
另请参阅:
我在反序列化过程中遇到了与未解决的前向引用相同的问题。我使用 https://www.logicbig.com/tutorials/misc/jackson/json-identity-reference.html 上提供的示例来检查和解决我的问题。
有一个很简单的class:
public class Order {
private int orderId;
private List<Integer> itemIds;
private Customer customer;
....
}
我向客户添加了@JsonCreator 静态工厂方法class,它没有引起任何问题。
现在,当我向 Order class 添加任何类型的 @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;
}
它还会导致未解析的前向引用。
要解决此问题,对于订单 class 您必须创建无参数构造函数(可以是私有的)。否则你将得到:
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.logicbig.example.Order
(no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
并且不得有任何带有@JsonCreator 注释的方法和构造函数,或带有@JsonProperty 注释的构造函数。
仅此而已。
我已经被 Jackson
的问题困扰了很长一段时间,我很想解决它。我有一个 JSON
,其中包含使用 ID 相互引用的对象,我需要将其反序列化为对象,但我在尝试这样做时一直得到 Unresolved forward references exception
。
我已经尝试使用上述 class 中的 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"
}
]
}
客户class
@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
}
购物车class
<!-- 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
对象,它引用了 Customer
对象,id 为 2
(在本例中是 John Sharp) .但我无法让它工作,当我尝试使用 ObjectMapper.readValue()
方法从 JSON 读取时,它给了我 "main" com.fasterxml.jackson.databind.deser.UnresolvedForwardReference
。
您应该在 属性 上使用 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}]}
另请参阅:
我在反序列化过程中遇到了与未解决的前向引用相同的问题。我使用 https://www.logicbig.com/tutorials/misc/jackson/json-identity-reference.html 上提供的示例来检查和解决我的问题。 有一个很简单的class:
public class Order {
private int orderId;
private List<Integer> itemIds;
private Customer customer;
....
}
我向客户添加了@JsonCreator 静态工厂方法class,它没有引起任何问题。
现在,当我向 Order class 添加任何类型的 @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;
}
它还会导致未解析的前向引用。
要解决此问题,对于订单 class 您必须创建无参数构造函数(可以是私有的)。否则你将得到:
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of
com.logicbig.example.Order
(no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
并且不得有任何带有@JsonCreator 注释的方法和构造函数,或带有@JsonProperty 注释的构造函数。
仅此而已。