Private Fields Serialization with JSON-B and JAX-RS 2.1 / Java EE 8

JSON-B from Java EE 8 serializes public fields or properties as default. For private field serialization:


public class Workshop {

    private String name;
    private int duration;

    public Workshop(String name, int duration) {
        this.name = name;
        this.duration = duration;
    }

}    

you will have to implement a PropertyVisibilityStrategy (checkout Java EE 8: Serializing POJOs with JSON-B):


    public class PrivateVisibilityStrategy implements PropertyVisibilityStrategy {
    
        @Override
        public boolean isVisible(Field field) {
            return true;
        }
    
        @Override
        public boolean isVisible(Method method) {
            return false;
        }
    
    }

...pass your custom configuration to the JsonbBuilder and return the instance with a ContextResolver:


    import javax.json.bind.Jsonb;
    import javax.json.bind.JsonbBuilder;
    import javax.json.bind.JsonbConfig;
    import javax.ws.rs.ext.ContextResolver;
    import javax.ws.rs.ext.Provider;
    
    @Provider
    public class JSONConfigurator implements ContextResolver {
    
        @Override
        public Jsonb getContext(Class type) {
            JsonbConfig config = new JsonbConfig().
                    withPropertyVisibilityStrategy(new PrivateVisibilityStrategy());
            return JsonbBuilder.newBuilder().
                    withConfig(config).
                    build();
        }
    }

Now your POJO's private fields are going to be used for JSON-mapping:


@Path("workshops")
public class WorkshopsResource {

    @GET
    public Workshop workshop() {
        return new Workshop("Java EE 8", 42);
    }

}

Result: {"duration":42,"name":"Java EE 8"}

Tested with Payara 5.

See you at Java EE Workshops at MUC Airport, particularly at the Effective Java EE 8 workshop

Comments:

Shouldn't it have a type parameter `... implements ContextResolver<Jsonb>`?

Posted by Rüdiger on October 19, 2018 at 06:13 AM CEST #

I use wildfly 14

If I create this Provider it is not used to deserialize the Classes. What am I doing wrong? Any suggestions?

Posted by chris on October 23, 2018 at 02:15 PM CEST #

Thanx for the tip!
I'd like to ask if there is a way to obtain the same Jsonb instance that we create in the ContextResolver when we want to use it programmatically?
My use case is that JSON arrives at a JAX-RS resource as form data (application/x-www-form-urlencoded)
and I'd like to use the same, configured Jsonb instance instead of re-creating another one ad-hoc.

Posted by Vagelis on January 22, 2019 at 05:33 PM CET #

@chris, @adam

This is not mentioned in the jax-rs 2.x specifications. This is just a Payara-only-Feature and shouldn't have been tagged JavaEE8.

See this issue on openliberty: https://github.com/OpenLiberty/open-liberty/issues/5903

Posted by Ben M. on February 11, 2019 at 09:08 AM CET #

My class had collections, which seems to require a public getter. Of course, now also the methods need to be visible to access the getter.

public class PrivateVisibilityStrategy implements PropertyVisibilityStrategy {
@Override public boolean isVisible(Field field) { return true; }
@Override public boolean isVisible(Method method) { return true; }
}

public class MyWorkshop extends Workshop {
private List<String> attendees;
public List<String> getAttendees() {
if ( attendees == null ) { attendees = new ArrayList<String>(); }
return attendees;
}
}

Posted by Mikko on March 06, 2019 at 02:59 PM CET #

Is it possible to have different jsonbconfig for different jaxrs resources?

I have two jaxrs resources. In the first I would like binary data to be encoded with BASE64 strategy. In the second, I wouldn't like that.

Posted by wxqy on December 04, 2019 at 07:19 AM CET #

Post a Comment:
  • HTML Syntax: NOT allowed
...the last 150 posts
...the last 10 comments
License