Джексон typeId не включен в сгенерированный JSON

1

У вас есть следующие классы:

public class BaseEntity<E> {
    public TrackedChange<E> trackChange;
}


@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({ @JsonSubTypes.Type(value=B.class, name="b_type") })
public abstract class A extends BaseEntity<A> implements Cloneable{
    public String aFoo;

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

@JsonTypeName("b_type")
public class B extends A {
    public String bFoo;
}

public class TrackedChange<E> {
    public E tracked;
}

public class Runner {

    public static void main(String[] args) throws JsonProcessingException, CloneNotSupportedException {

        B bInstance = new B();
        bInstance.bFoo = "bFoo";
        bInstance.aFoo = "aFoo";
        B clone = (B) bInstance.clone();
        bInstance.trackChange = new TrackedChange<A>();
        bInstance.trackChange.tracked = clone;
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(bInstance));
    }
}

Сгенерированный JSON:

{
   "type":"b_type",
   "trackChange":{
      "tracked":{
         "trackChange":null,
         "aFoo":"aFoo",
         "bFoo":"bFoo"
      }
   },
   "aFoo":"aFoo",
   "bFoo":"bFoo"
}

Тип ("type":"b_type") не включен в объект trackChange.tracked. Как решить эту проблему?

EDIT: Наконец, я использовал JsonTypeInfo.As.EXISTING_PROPERTY который был представлен после выпуска 2.3.0. Он использует существующее свойство для определения фактического типа.

Теги:
polymorphism
serialization
jackson

1 ответ

2
Лучший ответ

Тип стирания на TrackedChange.tracked - ваша проблема. Во время выполнения ваш тип теряется из-за стирания типа, и сериализатор Jackson не может определить тип и, следовательно, не распознает его как B и не находит для него @JsonTypeInfo; таким образом, во время выполнения Джексон считывает TrackedChange.tracked как тип Object.

Существуют различные способы смягчения стирания стилей в Джексоне, но они, как правило, основываются на дженериках коллекций.

Там только один способ в основном достичь вашей цели, которую я вижу, вы можете настроить ObjectMapper следующим образом:

ObjectMapper mapper = new ObjectMapper();
TypeResolverBuilder<?> typer = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE);
typer = typer.init(JsonTypeInfo.Id.CLASS, null);
typer = typer.inclusion(JsonTypeInfo.As.PROPERTY);
typer = typer.typeProperty("type");
mapper.setDefaultTyping(typer);

Это будет регистрировать конфигурацию конфигуратора типа для объектов и TrackedChange.tracked типов во время сериализации (это охватывает случай TrackedChange.tracked). К сожалению, я не вижу возможности предварительно зарегистрировать, что этот configure будет использовать соответствующее имя b_type как в вашем примере. Самое лучшее, что у меня есть, - это изменить конфигурацию вашего класса, чтобы использовать следующее, которое соответствует описанному выше поведению:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "type")

Предоставление вывода следующим образом:

{
  "type" : "so.json.typeinfo.B",
  "trackChange" : {
    "tracked" : {
      "type" : "so.json.typeinfo.B",
      "trackChange" : null,
      "aFoo" : "aFoo",
      "bFoo" : "bFoo"
    }
  },
  "aFoo" : "aFoo",
  "bFoo" : "bFoo"
}
  • 0
    Спасибо! Я изменил JsonTypeInfo.Id.CLASS на JsonTypeInfo.Id.NAME, и он начал работать как положено!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню