9

I have a class (let us call it a Piece) containing a member of type com.jme3.math.ColorRGBA. With a default Jackson serialization the member is serialized not only as its members r, g, b and a, but then also using getters like getAlpha.

As this is obviously redundant, I would like to control the serialization and to serialize only those primary members. Are there some annotations that I can write to my class to control serialization of members with types not under my control, or some custom serializers for them?

I can probably write a custom serializer for the Piece class, though other than ColorRGBA serializer being too verbose, default serialization works fine for me for all other properties of Piece, therefore I would like to customize as little of it as possible.

I do not want to modify jme3 library source, the solution should be implemented outside of the ColorRGBA class.

Suma
  • 33,181
  • 16
  • 123
  • 191
  • 1
    Closely related: http://stackoverflow.com/questions/15378853/jackson-custom-serializer-that-overrides-only-specific-fields?rq=1 – Suma Jan 27 '15 at 16:52

3 Answers3

25

You can use a mixin to make sure that the class is serialized as per your needs. Consider the following:

// The source class (where you do not own the source code)
public class ColorRGBA {
    public float a; // <-- Want to skip this one
    public float b;
    public float g;
    public float r;
}

Then, create the mixin where you ignore the a property.

// Create a mixin where you ignore the "a" property
@JsonIgnoreProperties("a")
public abstract class RGBMixin {
    // Other settings if required such as @JsonProperty on abstract methods.
}

Lastly, configure your mapper with the mixin:

ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(ColorRGBA.class, RGBMixin.class);
System.out.println(mapper.writeValueAsString(new ColorRGBA()));

The output will be:

{"b":0.0,"g":0.0,"r":0.0}

Note that the method ObjectMapper.addMixInAnnotations is deprecated from Jackson 2.5 and should be replaced with the more fluent version:

mapper.addMixIn(ColorRGBA.class, RGBMixin.class);

The JavaDocs can be found here

wassgren
  • 18,651
  • 6
  • 63
  • 77
  • Looks promising, however some more effort will be needed, as with recent Jackson `addMixInAnnotations` is deprecated in `ObjectMapper` and one needs to use a [feature module](http://wiki.fasterxml.com/JacksonMixInAnnotations). – Suma Jan 27 '15 at 14:56
  • 1
    @Suma, you can simply replace the `addMixInAnnotations` with a call to `addMixIn`, that will do the trick (answer updated to reflect Jackson 2.5) – wassgren Jan 27 '15 at 19:57
  • It also appears that, even with Jackson 2.8, an alternative implementation of the `RGBMixin` class with the use of `@JsonIngore` annotation doesn't work for some reason e.g. `public abstract class RGBMixin { @JsonIgnore String a; }`. I'm not sure whether it's a libray bug or intended as I couldn't find any documentation that clearly explains this behaviour. – RZet Apr 19 '17 at 11:09
1

Option A

If you control the source of the class, can put this above class:

@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
public class ColorRGBA {

Option B

Otherwise you can set up an object mapper to ignore getters:

ObjectMapper mapper = new ObjectMapper();
mapper.setVisibilityChecker(mapper.getSerializationConfig().getDefaultVisibilityChecker()
                .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));

mapper.writeValue(stream, yourObject);

Option C

For more complicated requirements, you can write your own VisibilityChecker implementation.

weston
  • 54,145
  • 21
  • 145
  • 203
  • No, I do not have any control over com.jme3.math, it is an external library. – Suma Jan 27 '15 at 14:30
  • @Suma I know, that's more for other visitors. For you, use option b. – weston Jan 27 '15 at 14:31
  • Thanks, look viable at first, but that would also modify behaviour for all other classes? For some classes getters / setters may be needed. The ideal solution should affect only my ColorRGBA member and nothing else (or at most all members of ColorRGBA type). – Suma Jan 27 '15 at 14:33
0

It is possible to write a custom serializer for the member only, using annotation for the member like this:

@JsonSerialize(using = CustomColorRGBASerializer.class)
ColorRGBA color;

See also this answer about how to custom-serialize a Date field.

Community
  • 1
  • 1
Suma
  • 33,181
  • 16
  • 123
  • 191