0

According to what I assume is the official user guide, http://json-b.net/users-guide.html, the engine should serialize any properties it finds, with or without bean accessor methods (I realize the Dog example uses public fields, but see the Person example for private fields).

Given these classes:

public class Rectangle {
    private double length1 = 0.0;
    @JsonbProperty("length2")
    private double length2 = 0.0;
    public double width = 0.0;
}

public class Rectangle2 {
    @JsonbProperty
    private double length = 0.0;

    private double width = 0.0;

    public double getLength() {
        return length;
    }

    public double getWidth() {
        return width;
    }
}

When I serialize it like this:

public class App2 {
    public static void main(String... argv) {
        Jsonb jsonb = JsonbBuilder.create();

        System.out.println("Rectangle: " + jsonb.toJson(new Rectangle()));
        System.out.println("Rectangle2: " + jsonb.toJson(new Rectangle2()));
    }
}

The output is this:

Rectangle: {"width":0.0}
Rectangle2: {"length":0.0,"width":0.0}

What I see is, in Rectangle, only width is serialized because it is public. length1 and length2 are ignored since they are private even though there is a property annotation on length2. Rectangle2 is fully serialized since it has bean methods.

Does it have to be this way? Requiring me to make all fields public and mutable to enable serialization seems like a huge limitation.

My dependencies are set up like this:

    <dependency>
        <groupId>javax.json.bind</groupId>
        <artifactId>javax.json.bind-api</artifactId>
        <version>1.0</version>
    </dependency>

    <dependency>
        <groupId>org.eclipse</groupId>
        <artifactId>yasson</artifactId>
        <version>1.0.2</version>
    </dependency>

    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.json</artifactId>
        <version>1.1.4</version>
    </dependency>
Andy Guibert
  • 41,446
  • 8
  • 38
  • 61
absmiths
  • 1,144
  • 1
  • 12
  • 21

1 Answers1

2

I found this reference about the spec and field visibility in the yasson source (org.eclipse.yasson.internal.model.PropertyValuePropagation.DefaultVisibilityStrategy):

    @Override
    public boolean isVisible(Field field) {
        //don't check field if getter is not visible (forced by spec)
        if (method != null && !isVisible(method)) {
            return false;
        }
        return Modifier.isPublic(field.getModifiers());
    }

I can't speak to the spec, but that jives with what I have been seeing - that the fields will only be serialized based on the visibility of the getter method.

I want my serialization to be exclusively driven by fields, and only fields I want serialized - so I went with a custom PropertyVisibilityStrategy which exposes no methods, and only fields with the JsonbProperty annotation. This gets me most of what I want:

    Jsonb jsonb = JsonbBuilder.newBuilder().withConfig(
        new JsonbConfig().withPropertyVisibilityStrategy(new PropertyVisibilityStrategy() {
            @Override
            public boolean isVisible(Field field) {
                return field.getAnnotation(JsonbProperty.class) != null;
            }

            @Override
            public boolean isVisible(Method method) {
                return false;
            }
        })
    ).build();
absmiths
  • 1,144
  • 1
  • 12
  • 21