java/jackson - don't serialize wrapping class
Asked Answered
B

2

6

When serializing a list of string with Jackson library, it provides correctly a JSON array of strings:

<mapper>.writeValue(System.out, Arrays.asList("a", "b", "c"));

[ "a", "b", "c" ]

However, the strings are wrapped/enclosed by a class in our code:

public static class StringWrapper {
    protected final String s;

    public String getS() {
        return s;
    }

    public StringWrapper(final String s) {
        this.s = s;
    }
}

When serializing a list of "string wrapers", I would like to have the same output as above. Now I get:

<mapper>.writeValue(System.out, Arrays.asList(new StringWrapper("a"), new StringWrapper("b"), new StringWrapper("c")));

[ {
  "s" : "a"
}, {
  "s" : "b"
}, {
  "s" : "c"
} ]

What is the most convenient method to do this? If possible, deserializing should work also.

Boykins answered 29/12, 2014 at 15:25 Comment(0)
T
11

You can use @JsonValue on your single getter

@JsonValue
public String getS() {
    return s;
}

From the javadoc,

Marker annotation similar to javax.xml.bind.annotation.XmlValue that indicates that results of the annotated "getter" method (which means signature must be that of getters; non-void return type, no args) is to be used as the single value to serialize for the instance. Usually value will be of a simple scalar type (String or Number), but it can be any serializable type (Collection, Map or Bean).

Trackless answered 29/12, 2014 at 15:28 Comment(3)
This seems to work perfectly! Thank you. I'll accept this as answer.Boykins
I had a class class MyClass { private Map<String, String> props; ... @JsonValue public Map<String, String> getProps() { return this.props } } Worked as advertised... The serialization of an instance with 2 entries properly showed { "key1" : "value1", "key2" : "value2" }! Thanks!Metaphysic
Works for Enums as well, e.g. public enum Operation { TEST("test"), REMOVE("remove"), ADD("add"), REPLACE("replace"), MOVE("move"), COPY("copy"); private String value; Operation(String value) { this.value = value; } @Override @JsonValue public String toString() { return value; } }Nathan
S
3

I see two possible options. If you own the StringWrapper class you can simply add the @JsonValue annotation on the getter.

@JsonValue
public String getS() { return s; }

If you are not allowed to change the object the following streaming solution works as well:

mapper.writeValueAsString(listOfStringWrappers.stream().map(sw -> sw.getS()).toArray());
Solemnize answered 29/12, 2014 at 15:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.