Spring REST JSON сериализация / десериализация составных полиморфных типов

Я использую Spring / Spring Boot и Spring MVC с @RestController

У меня есть объекты составной модели:

public abstract class BaseQuery {

    private final Long characteristicId;

...

}

public abstract class ComparableQuery extends BaseQuery {

    private final Object value;

    private final String comparisonOperator;

...

}

public class GreaterOrEqualQuery extends ComparableQuery {

    public GreaterOrEqualQuery(Long characteristicId, Object value) {
        super(characteristicId, value, ">=");
    }

}

public class EqualQuery extends ComparableQuery {

    public EqualQuery(Long characteristicId, Object value) {
        super(characteristicId, value, "=");
    }

}

public class GreaterQuery extends ComparableQuery {

    public GreaterQuery(Long characteristicId, Object value) {
        super(characteristicId, value, ">");
    }

}

public class CompositQuery extends BaseQuery {

    private final String operator;
    private final BaseQuery[] queries;

    public CompositQuery(Long characteristicId, Operator operator, BaseQuery... queries) {
        super(characteristicId);
        this.operator = operator.value;
        this.queries = queries;
    }

...

}

и т.п.

Пример использования этой модели выглядит, например, так:

Set<BaseQuery> queries = new HashSet<>();

BaseQuery megapixelCharacteristicQuery = new CompositQuery(megapixelCharacteristic.getCharacteristicId(), CompositQuery.Operator.AND, new GreaterOrEqualQuery(megapixelCharacteristic.getCharacteristicId(), 10), new LessOrEqualQuery(megapixelCharacteristic.getCharacteristicId(), 50));
queries.add(megapixelCharacteristicQuery);
queries.add(new EqualQuery(androidCharacteristic.getCharacteristicId(), true));

Сериализованный объект JSON для Set<BaseQuery> queries выглядит так:

[
   {
      "operator":"AND",
      "queries":[
         {
            "value":10,
            "comparisonOperator":"\u003e\u003d",
            "characteristicId":391
         },
         {
            "value":50,
            "comparisonOperator":"\u003c\u003d",
            "characteristicId":391
         }
      ],
      "characteristicId":391
   },
   {
      "value":true,
      "comparisonOperator":"\u003d",
      "characteristicId":383
   }
]

Я должен передать этот или аналогичный JSON из клиентского приложения (AngularJS) в мою конечную точку REST API серверной части, чтобы получить правильно десериализованную модель, как описано выше (установите соответствующие записи, такие как CompositQuery или EqualQuery).

Прямо сейчас моя внутренняя логика приложения Spring на моем контроллере Rest не может правильно десериализовать этот JSON с соответствующими классами.

Есть ли способ в Spring предоставить некоторую метаинформацию (или что-то еще) этому JSON, чтобы помочь Spring правильно десериализовать эту структуру?


person alexanoid    schedule 22.12.2016    source источник


Ответы (1)


Вы можете добиться этого, используя аннотации Джексона в суперклассе, например:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "javaclass")
@JsonSubTypes({
    @Type(value = GreaterOrEqualQuery.class),
    @Type(value = EqualQuery.class)
    //and so on...
})
public abstract class BaseQuery {
    ...
}

Это добавит свойство javaclass в представление json, которое является полным именем в случае use = JsonTypeInfo.Id.CLASS. Чтобы упростить значение этого свойства, рассмотрите различные варианты параметра use для @JsonTypeInfo (например, JsonTypeInfo.Id.NAME).

person Oleg Kurbatov    schedule 23.12.2016