Полиморфная десериализация Джексона через поле - PullRequest
0 голосов
/ 25 июня 2018

скажем, у меня есть класс

public class A{
  private UUID typeId;
  private B data;
}

public abstract class B{
  private String a;
}

public class BChildOne extends B{
  ... some variables
}

public class BChildTwo  extends B{
  ... some variables
}

тип класса B изменяется в соответствии с typeId A, поэтому, если typeId для A равен «XXX», тип поля данных равен BChildOne, а если typeId для A равен «YYY», тип поля данных равен BChildTwo.

как мне этого достичь?

так что я попробовал это;

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility =
JsonAutoDetect.Visibility.NONE, setterVisibility = 
JsonAutoDetect.Visibility.NONE)
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = 
JsonTypeInfo.As.EXTERNAL_PROPERTY , property = "typeId")
@JsonSubTypes({
 @JsonSubTypes.Type(value = BChildOne.class, name = "40ad2fe6-e672-4f0e- 
986e- 
 619c7a1a3223") }
 )
 public abstract class B{

но я получил следующую ошибку;

Неожиданный токен (END_OBJECT), ожидаемый FIELD_NAME: отсутствует свойство 'typeId', которое должно содержать идентификатор типа (для класса B)

, что очевидно, поскольку поле typeId находится в классе A, а не B.

Ответы [ 2 ]

0 голосов
/ 25 июня 2018

Предполагается, что ваши документы JSON имеют вид:

{
  "type": "foo",
  "data": {
    "someCommonProperty": "common property",
    "fooProperty": "foo specific property"
  }
}
{
  "type": "bar",
  "data": {
    "someCommonProperty": "common property",
    "barProperty": "bar specific property"
  }
}

Вы можете использовать:

public class Wrapper {

    private String type;

    @JsonTypeInfo(use = Id.NAME, property = "type", include = As.EXTERNAL_PROPERTY)
    @JsonSubTypes(value = { 
        @JsonSubTypes.Type(value = Foo.class, name = "foo"),
        @JsonSubTypes.Type(value = Bar.class, name = "bar") 
    })
    private AbstractData data;

    // Getters and setters
}
public abstract class AbstractData {

    private String someCommonProperty;

    // Getters and setters
}
public class Foo extends AbstractData {

    private String fooProperty;

    // Getters and setters
}
public class Bar extends AbstractData {

    private String barProperty;

    // Getters and setters
}

В этом подходе @JsonTypeInfo устанавливается для использования type в качестве внешнего свойства , чтобы определить правильный класс для сопоставления свойства data. Документ JSON можно десериализовать следующим образом:

ObjectMapper mapper = new ObjectMapper();
Wrapper wrapper = mapper.readValue(json, Wrapper.class);  
0 голосов
/ 25 июня 2018

У меня была одна и та же проблема сериализации, и я сделал такую ​​реализацию.см. код ниже.

    protected Entity serialize(Object entity) throws Exception {
    try {
        if ( entity instanceof AbstractProcessRequest ) {
            AbstractProcessRequest request = (AbstractProcessRequest) entity;
            String value = mapper.writeValueAsString(request.prepareJSONRequest());
            logger.info("Telesales String json request " + value);
            return new Entity(value, UTF_8);
        } else {
            String value = mapper.writeValueAsString(entity);
            return new StringEntity(value, UTF_8);
        }
    } catch (Exception e) {
        logger.error("Telesales --> Error occured serializing entity", e);
        throw e;
    }
}

Для достижения общей структуры в некотором классе обслуживания создается метод execute, как показано ниже.

private <T> T execute(Object entity, Class<T> clazz, HttpRequestBase request, String contentType) throws Exception {
...