解決FastJson中"$ref重複引用"的問題,先來看一個例子吧:前端
public static void main(String[] args) { UserGroup userGroup = new UserGroup().setName("UserGroup"); User user = new User("User"); for (int i = 0; i < 3; i++) { userGroup.addUser(user); } Console.log(JSON.toJSONString(userGroup)); } @Data @AllArgsConstructor static class User { private String name; } @Data @Accessors(chain = true) static class UserGroup { private String name; private List<User> users = Lists.newArrayList(); public UserGroup addUser(User user) { this.getUsers().add(user); return this; } }
輸出結果:java
{"name":"UserGroup","users":[{"name":"User"},{"$ref":"$.users[0]"},{"$ref":"$.users[0]"}]}
<!--- more --->
上面的現象就是將user對象的引用重複使用形成了重複引用問題,Fastjson默認開啓引用檢測將相同的對象寫成引用的形式:json
{"$ref": "$"} // 引用根對象 {"$ref":"@"} // 引用本身 {"$ref":".."} // 引用父對象 {"$ref":"../.."} // 引用父對象的父對象 {"$ref":"$.members[0].reportTo"} // 基於路徑的引用
目前來講,前端尚未一個很好的辦法來解析這樣的JSON格式。this
除了上面的重複引用外, 還衍生出了另一個概念:"循環引用",下面來看下二者之間的區別吧:code
再來看一個循環引用的例子:對象
public static void main(String[] args) { Order order = new Order().setName("Order"); Item item = new Item().setName("Item"); item.setOrder(order); order.setItem(item); Console.log(JSON.toJSONString(order)); Console.log("----------------------------"); Console.log(JSON.toJSONString(item)); } @Data @Accessors(chain = true) static class Order { private String name; private Item item; } @Data @Accessors(chain = true) static class Item { private String name; private Order order; }
{"item":{"name":"Item","order":{"$ref":".."}},"name":"Order"} ---------------------------- {"name":"Item","order":{"item":{"$ref":".."},"name":"Order"}}
StackOverflowError
)JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect)
@JSONField(serialize=false)
)public static void main(String[] args) { UserGroup userGroup = new UserGroup().setName("UserGroup"); User user = new User("User"); for (int i = 0; i < 3; i++) { User duplicateUser = new User(); BeanUtil.copyProperties(user, duplicateUser); userGroup.addUser(duplicateUser); } Console.log(JSON.toJSONString(userGroup)); }