杰克逊将动态房产价值提升一级

时间:2014-12-19 12:20:28

标签: java jackson

我在建模服务器响应时遇到问题,其中一些看起来像这样:

{
    "_links":{
        "self":{
            "href":"http:\/\/example.com"
        }
    },
    "_embedded":{
        "category":{
           <...data...>
        }
    }
}

{
    "_links":{
        "self":{
            "href":"http:\/\/example.com"
        }
    },
    "_embedded":{
        "episodes":[
           <...list_data...>
        ]
    }
}

似乎&#34; _embedded&#34; property只有一个JSON对象,该对象只有一个属性(用不同的名称命名)和实际数据。

我想创建一些通用的POJO类来支持这类响应,例如:

public abstract class EmbeddedResponse<T> {

    @JsonProperty("_embedded")
    private T embedded;

    public T getEmbedded() {
        return embedded;
    }

    ... <other_members> ...
}

public class CategoriesResponse extends EmbeddedResponse<List<Category>> {

}

调用&#39; getEmbedded()&#39;将返回类别列表(或剧集或任何内容)。

我现在正在使用自定义反序列化,但是没有太大的成功,我想保持代码库最小化。

2 个答案:

答案 0 :(得分:0)

解决方案,抽象POJO类:

public class EmbeddedResponse<T>  {

    @JsonProperty("_embedded")
    @JsonDeserialize( using = EmbeddedResponseDeserializer.class )
    private T embedded;

    public T getEmbedded() {

        return embedded;
    }
}

POJO的实际回复:

public class CategoriesResponse extends EmbeddedResponse<List<Category>> {

}

有问题的JSON的反序列化器:

public class EmbeddedResponseDeserializer extends JsonDeserializer<Object> implements ContextualDeserializer {

private JavaType javaType;

@Override
public Object deserialize( JsonParser jsonParser, DeserializationContext ctxt ) throws IOException {

    ObjectCodec objectCodec = jsonParser.getCodec();

    JsonNode node = objectCodec.readTree(jsonParser);

    // Get first it might require correction
    String fieldName = node.fieldNames().next();

    JsonNode skippedNode = node.get( fieldName );

    return objectCodec.readValue( skippedNode.traverse(), javaType );
}

@Override
public JsonDeserializer<?> createContextual( DeserializationContext ctxt, BeanProperty property ) throws JsonMappingException {

    javaType = property.getType();

    return this;
}

}

可能需要更多的tweek,但此时此解决方案正在运行

答案 1 :(得分:-1)

在建模对象时,我会使用Java 8 Optional对象。通过这种方式,您可以获得灵活的模型和良好的编程模型。使用ifPresent-method

因此,根类可以按照以下方式建模:

public class Response {
    private Embedded embedded;
    private Links links;

    @JsonCreator
    public Response(
            @JsonProperty("_links") final Links links, 
            @JsonProperty("_embedded") final Embedded embedded) {
        this.links = links;
        this.embedded = embedded;
    }

    public Embedded embedded() {
        return embedded;
    }

    public Links links() {
        return links;
    }
}

定义嵌入内容的对象(即类别或剧集)可以这样建模:

public class Embedded {
    private final Category category;
    private final List<Episode> episodes;

    @JsonCreator
    public Embedded(
            @JsonProperty("episodes") final List<Episode> episodes, 
            @JsonProperty("category") final Category category) {
        this.episodes = episodes;
        this.category = category;
    }

    public Optional<Category> category() {
        return Optional.ofNullable(category);
    }

    public Optional<List<Episode>> episodes() {
        return Optional.ofNullable(episodes);
    }
}

对这些对象进行编程时,可以使用以下模式:

final InputStream resource = ...; // retrieve a stream somehow

// Map the stream to the response object
final Response response = new ObjectMapper().readValue(resource, Response.class);

// Use the Optional-style for processing category data
response.embedded().category().ifPresent(category -> {
    // do category stuff with the Category-object
});

// Once more, use the Optional-style - this time for processing episodes data    
response.embedded().episodes().ifPresent(episodes -> {
    // do episodes stuff with the List of Episodes
});