我已经这样定义了一个bean:
public static class TestBean {
private String a;
private Long b;
public TestBean(String a, Long b) {
this.a = a;
this.b = b;
}
public String getA() {
return a;
}
public Long getB() {
return b;
}
}它对一些业务进行建模,而我不需要实例化它(使用JPA)。我的一些API允许用户使用Jackson (通过JAX-RS)检索这个bean的视图,并将其序列化为JSON,我想为这个视图添加一个相关链接的列表。
通常的Jackson JSON序列化是(对于a= "aa“和b= 2L):
{"a":"aa","b":2}我想让这些链接显示为
{"a":"aa","b":2,
"links":[{"rel":"rel","href":"href://"},{"rel":"rel2","href":"href://2"}]}可能的解决方法
我不希望将getLinks()方法添加到我的bean中,它特定于此视图。
简单地使用复合对象将产生类似以下的序列化:
{"data":{"a":"aa","b":2},"links":[{"rel":"rel","href":"href://"}]}我可以接受,但这并不是我最终想要的。
当前解决方案
我希望避免操作JSON字符串或将其重新加载到Map中以插入额外的值。就目前而言,我提出的解决方案看起来非常复杂:
当前可怕的解决方案:
//a composite view object
public abstract class AddedLinksView<K> {
private final K resource;
private final Link[] links;
public AddedLinksView(K resource) {
this.resource = resource;
links = buildLinks(resource);
}
public abstract Link[] buildLinks(K resource);
public K getResource() {
return resource;
}
public Link[] getLinks() {
return links;
}
}
//a specific bean serializer
private static class RawBeanSerializer extends BeanSerializer {
public RawBeanSerializer(BeanSerializerBase ser) {
super(ser);
}
//this is like the standard serialize but without the start and end tags
public void rawSerialize(Object bean, JsonGenerator jgen, SerializerProvider provider) throws IOException,
JsonGenerationException {
if (_propertyFilterId != null) {
serializeFieldsFiltered(bean, jgen, provider);
} else {
serializeFields(bean, jgen, provider);
}
}
}
@Test
public void usingModule() throws Exception {
// basic module metadata just includes name and version (both for troubleshooting; but name needs to be unique)
SimpleModule module = new SimpleModule("EnhancedDatesModule", new Version(0, 1, 0, "alpha"));
//adding a serializer for the composite view
module.addSerializer(new JsonSerializer<AddedLinksView>() {
@Override
public Class<AddedLinksView> handledType() {
return AddedLinksView.class;
}
@Override
public void serialize(AddedLinksView value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
jgen.writeStartObject();
//looking up the bean serializer that will be used for my resource
JsonSerializer<Object> ser = provider.findTypedValueSerializer(value.getResource().getClass(), true,
null);
if (ser instanceof BeanSerializerBase) {
//cloning it in a sub class that makes it possible to 'inline' the serialization
RawBeanSerializer openSer = new RawBeanSerializer((BeanSerializerBase) ser);
openSer.rawSerialize(value.getResource(), jgen, provider);
}
//adding my links
jgen.writeArrayFieldStart("links");
for (Link link : value.getLinks()) {
jgen.writeObject(link);
}
jgen.writeEndArray();
jgen.writeEndObject();
}
});
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(module);
AddedLinksView<TestBean> view = new AddedLinksView<TestBean>(new TestBean("aa", 2L)) {
@Override
public Link[] buildLinks(TestBean resource) {
return new Link[] { new Link("rel", "href://"), new Link("rel2", "href://2") };
}
};
System.out.println("useModule json output: " + mapper.writeValueAsString(view));
}我是不是错过了杰克逊身上的一些显而易见的东西来实现这一点?或者我的需求已经完全偏离目标了吗?
发布于 2012-02-14 06:48:21
没有真正的方法可以从外部将内容注入POJO进行序列化:但是您可能有兴趣查看@JsonAnyGetter,它至少允许将java.util.Map的内容作为POJO的额外属性添加。
发布于 2012-02-13 21:55:52
这能回答你的问题吗:http://wiki.fasterxml.com/JacksonFeatureUpdateValue
我不确定您是否可以避免映射。你可以使用Dozer来帮助你。
这应该会对你有所帮助:Tools for merging java beans
https://stackoverflow.com/questions/9260800
复制相似问题