What is the best way to do inline serialization of JSON data using JACKSON?

I have a bean defined as such:

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; } } 

It models some types of business, and I cannot create it (using JPA). Some of my APIs allow the user to get an idea of ​​serializing bean as JSON using Jackson (via JAX-RS), and I would like to add a list of related links to this view.

Jackson's usual JSON serialization would be (for a = "aa" and b = 2L):

 {"a":"aa","b":2} 

And I would like the links to appear as

 {"a":"aa","b":2, "links":[{"rel":"rel","href":"href://"},{"rel":"rel2","href":"href://2"}]} 

Possible workaround

I would prefer not to add the getLinks () method to my bean, it is defined for this view.

Just using a compound object will result in serialization, for example:

 {"data":{"a":"aa","b":2},"links":[{"rel":"rel","href":"href://"}]} 

With whom I could live, but this is not what I was looking for in the long run.

Current solution

I would like to avoid manipulating the JSON string or reloading it in Map to insert my extra values. At the moment, the solution I came up with looks terribly confusing:

Current scary decision:

 //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)); } 

Did I miss something obvious in Jackson to achieve this? Or am I completely unfamiliar with my requirements?

+4
source share
2 answers

There is no real way to input things into the POJO from outside for serialization: but you might be interested in checking out @JsonAnyGetter , which at least allows you to simply add java.util.Map content as additional properties for the POJO.

+3
source

Will this answer your question: http://wiki.fasterxml.com/JacksonFeatureUpdateValue

I'm not sure you can avoid matching. You can use Dozer to help.

This should help you: java beans merge tools

0
source

Source: https://habr.com/ru/post/1396191/


All Articles