Specific MessageBodyWriter for field

醉酒当歌 提交于 2019-12-03 16:30:43
Perception

Unfortunately, this is not how message body writers work. The JAX-RS implementation will locate a writer, to be used in serialization, based on the type being returned from your resource method. So in your case, with a custom writer defined for Bar, with this resource method:

@GET @Path("bar")  
public Bar getBar() { return new Bar(...); }

the JAX-RS provider will serialize Bar using your custom writer. However for this resource method:

@GET @Path("foo")  
public Foo getFoo() { return new Foo(...); }

you do not have a custom writer defined, and serialization will be handled by the first matching (default) provider that can handle the combination of return class and content-type. A key thing to remember is that, unlike typical JSON and XML serialization libraries, JAX-RS entity providers are not recursive. Aka, for a given object A being returned in a resource method, the provider will attempt to locate a custom writer only for A, and not for any of the types included in A as variables.

Since you are using Jackson though, why not just define a custom serializer for your Bar class? That will handle pretty much every scenario you described:

public class BarSerializer extends JsonSerializer<Bar> {

    @Override
    public void serialize(final Bar value, final JsonGenerator jgen,
            final SerializerProvider provider) throws IOException,
            JsonProcessingException {

        jgen.writeStartObject();
        jgen.writeFieldName("myBar");
        jgen.writeString(value.getTwo());
        jgen.writeEndObject();
    }
}

You tell Jackson to use this custom serializer thusly:

@JsonSerialize(using=BarSerializer.class)
class Bar {
   int one;
   String two;
}

Lastly, don't forget that if you anticipate getting JSON back in the same form as you serialized, that you will also need a custom JsonDeserializer.

To get it to work, you need the jackson-mapper and jackson-jaxrs jars in your classpath (and probably the jackson-core one as well).

The JAX-RS runtime will only look up one MessageBodyWriter for the object returned by the resource method (see sectioin "4.2.2 Message Body Writer" in the specification), then that single MessageBodyWriter has complete control over the serialization of the entire object graph to be returned to the client.

In order to implement the behavior you wanted, you would need a custom MessageBodyWriter per media type, that is willing to delegate the serialization of a part of the object graph to another writer whenever it encounters a specific type in the graph, and then resume its own logic. Obtaining the delegate writer for the specific type wouldn't be a big problem (inject a javax.ws.rs.ext.Providers and call getMessageBodyWriter()), but I don't think the existing xml/json/etc serializers are implemented with such kind of extensions in mind, so I guess you couldn't just relay on them. Reimplementing an xml marshaller just for this is not an attractive option either.

Refer the below post for writing custom message body writer for your Java object's serialization.

http://h2labz.blogspot.in/2014/12/marshalling-java-to-json-in-jax-rs.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!