【问题标题】:Json polymorphism with Jackson and Json without wrapper object具有杰克逊和没有包装对象的 Json 的 Json 多态性
【发布时间】:2017-01-13 20:57:09
【问题描述】:

我有以下 Java bean:



    /**
     * The top container. It uses generics.
     */
    public class Response {
      @JsonTypeInfo(
          use = JsonTypeInfo.Id.NAME,
          include = JsonTypeInfo.As.WRAPPER_OBJECT,
          property = "type"
      )
      @JsonSubTypes({
        @JsonSubTypes.Type(name = "AContent", value = A.class),
        @JsonSubTypes.Type(name = "BContent", value = B.class),        
      })  
      private E object;
    }

    /**
     * First type
     */ 
    @JsonRootName("AContent")
    public class A {
        ...
    }

    /**
     * Second type
     */ 
    @JsonRootName("BContent")
    public class B {
        ...
    }

处理请求时,我只期望以下输出:



{
    AContent: { ...}
}

但是,我得到以下输出:



{
    object: {
        AContent: { ...}
    }
}

元素“AContent”被包装到对象元素中。我不想要通用的包装器对象。我也不想直接在泛型对象中设置对象类型。

我想直接在根元素内输出“AContent”。

我们如何通过 Jackson 实现这一目标?

提前感谢您的帮助。

最好的问候,

黄鸭

【问题讨论】:

  • 至于序列化,您始终可以使用跳过 Request 并直接转到 object 的自定义序列化程序,但反序列化会比较棘手。
  • 我想让 jersey/jackson 自动序列化对象。是否可以通过杰克逊注释来实现?
  • 如果您有能力引入 AB 的基本实体,还有另一种解决方案。
  • 我可以引入 A 和 B 的基本实体。这个解决方案是什么?你能提供一个例子吗?预先感谢您的帮助。最好的问候

标签: java json jersey jackson


【解决方案1】:

既然你说你可以为 A 和 B 提供基础实体,那么解决方案将是:

@JsonSerialize(using = ResponseSerializer.class)
public class Response<T> {
    private T object;  
    ...
}

基础实体(其他人必须扩展它):

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.WRAPPER_OBJECT
)
@JsonSubTypes({
        @JsonSubTypes.Type(name = "AContent", value = EntityA.class),
        @JsonSubTypes.Type(name = "BContent", value = EntityB.class),
})
public class Entity {
    ...
}

和序列化器:

public class ResponseSerializer extends JsonSerializer<Response> {
    @Override
    public void serialize(Response value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        Class<?> responseClass = value.getObject().getClass();
        JavaType responseJavaType = serializers.constructType(responseClass);
        gen.writeStartObject();
        gen.writeFieldName(serializers.findTypeSerializer(responseJavaType).getTypeIdResolver().idFromValue(value.getObject()));
        serializers.findValueSerializer(responseClass).serialize(value.getObject(), gen, serializers);
        /* Here you must manually serialize other properties */
        /* Like gen.writeStringField("property", value.getProperty()); */
        gen.writeEndObject();
    }
}

附:我删除了对输出没有影响的额外注释。

【讨论】:

  • 非常感谢chimmi。它与带有 JsonTypeInfo 和 JsonSubTypes 注释的公共基础实体以及 getObject() 方法上的 JsonValue 注释完美配合。
  • 这个解决方案有一个问题(jsonValue注解):我在Request bean中看不到其他属性了。比如Request类中,如果我添加一个新的属性,json结果中就不会显示了。
  • @yellowduck 您的问题没有表明 Response 中还有其他属性,这就是为什么我认为 JsonValue 就足够了。无论如何,我已经用自定义序列化程序替换了我的答案,至少你可以手动序列化其他属性。而且,恐怕这是你能得到的最好的解决方案,至少是我能做的最好的。
  • 我不知道是否有更好的解决方案,但它可以通过扩展 JsonSerializer 来工作。谢谢@chimmi 的帮助。你太棒了
  • @yellowduck 如果我的解决方案适合您,请考虑接受我的回答
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 2014-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-10
  • 1970-01-01
相关资源
最近更新 更多