Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't @JsonUnwrapped work for Lists?

Tags:

jackson

I am using Jackson 2.1.0. Given:

public static final class GetCompanies
{
    private final List<URI> companies;

    /**
     * Creates a new GetCompanies.
     * <p/>
     * @param companies the list of available companies
     * @throws NullPointerException if companies is null
     */
    @JsonCreator
    public GetCompanies(@JsonUnwrapped @NotNull List<URI> companies)
    {
        Preconditions.checkNotNull(companies, "companies");

        this.companies = ImmutableList.copyOf(companies);
    }

    /**
     * @return the list of available companies
     */
    @JsonUnwrapped
    @SuppressWarnings("ReturnOfCollectionOrArrayField")
    public List<URI> getCompanies()
    {
        return companies;
    }
}

When the input list contains http://test.com/, Jackson generates:

{"companies":["http://test.com/"]}

instead of:

["http://test.com/"]

Any ideas?

UPDATE: See https://github.com/FasterXML/jackson-core/issues/41 for a related discussion.

like image 735
Gili Avatar asked Nov 14 '12 20:11

Gili


People also ask

What is@ JsonProperty annotation?

@JsonProperty is used to mark non-standard getter/setter method to be used with respect to json property.

What does JsonUnwrapped do?

JsonUnwrapped is used to indicate that a property should be serialized unwrapped, i.e. the target property will not be serialized as JSON object but its properties will be serialized as flattened properties of its containing Object.

What is JsonAnySetter?

@JsonAnySetter allows a setter method to use Map which is then used to deserialize the additional properties of JSON in the similar fashion as other properties.

What is @JsonValue?

JsonValue represents an immutable JSON value. A JSON value is one of the following: an object ( JsonObject ), an array ( JsonArray ), a number ( JsonNumber ), a string ( JsonString ), true ( JsonValue. TRUE ), false ( JsonValue. FALSE ), or null ( JsonValue.


1 Answers

In this case, if this was to work, you'd end up trying to produce following:

{ "http://test.com" }

which is not legal JSON. @JsonUnwrapped really just removes one layer of wrapping. And although it theoretically could be made to work for "arrays in arrays" case, it does not. And in fact I wonder if adding this feature was a mistake: mostly because it encourages use that is often against data-binding best practices (simplicity, one-to-one mapping).

But what would work instead is @JsonValue:

@JsonValue
private final List<URI> companies;

which means "use value of this property instead of serializing the object that contains it".

And the creator method would actually work as-is, no need for either @JsonUnwrapped or @JsonProperty.

Here is the corrected code:

public static final class GetCompanies
{
    private final List<URI> companies;

    /**
     * Creates a new GetCompanies.
     * <p/>
     * @param companies the list of available companies
     * @throws NullPointerException if companies is null
     */
    @JsonCreator
    public GetCompanies(@NotNull List<URI> companies)
    {
        Preconditions.checkNotNull(companies, "companies");

        this.companies = ImmutableList.copyOf(companies);
    }

    /**
     * @return the list of available companies
     */
    @JsonValue
    @SuppressWarnings("ReturnOfCollectionOrArrayField")
    public List<URI> getCompanies()
    {
        return companies;
    }
}
like image 155
StaxMan Avatar answered Sep 29 '22 18:09

StaxMan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!