Джексон: неразрешенные прямые ссылки при попытке десериализации JSON в объекты Java - PullRequest
1 голос
/ 06 апреля 2019

Я застрял на проблеме с Jackson уже довольно давно, и мне не терпится ее решить.У меня есть JSON, в котором есть объекты, ссылающиеся друг на друга с идентификаторами, и мне нужно десериализовать его в объекты, но я продолжаю получать 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
}

Класс ShoppingCart


<!-- 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 объект с идентификатором 2 (в данном случае Джон Шарп).Но я просто не могу заставить его работать, и это дает мне "main" com.fasterxml.jackson.databind.deser.UnresolvedForwardReference, когда я пытаюсь читать из JSON методом ObjectMapper.readValue().

Ответы [ 2 ]

0 голосов
/ 24 июля 2019

У меня была такая же проблема с Unresolved Forward Reference во время десериализации. Я использовал пример, приведенный на https://www.logicbig.com/tutorials/misc/jackson/json-identity-reference.html, чтобы проверить и решить мою проблему. Есть очень простой класс:

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

Я добавил статический метод @JsonCreator к классу Customer, и он не вызвал никаких проблем.

Теперь, когда я добавляю любой класс @JsonCreator (статический метод или конструктор) в класс Order, я сразу получаю неразрешенную прямую ссылку. Что интересно, когда я добавляю следующий конструктор, в котором присутствуют только аннотации @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 (не существует создателей, как конструкция по умолчанию): невозможно десериализовать из значения объекта (без делегата или свойства Создатель)

и НЕ ДОЛЖНЫ быть какие-либо аннотированные методы и конструкторы @JsonCreator или конструкторы с аннотациями @JsonProperty.

И это все.

0 голосов
/ 06 апреля 2019

Вы должны использовать 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}]}

Смотри также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...