Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow inlining/unwrapping of value from single-component JSON array #381

Closed
yinzara opened this issue Jan 7, 2014 · 10 comments
Closed

Allow inlining/unwrapping of value from single-component JSON array #381

yinzara opened this issue Jan 7, 2014 · 10 comments
Milestone

Comments

@yinzara
Copy link
Contributor

yinzara commented Jan 7, 2014

Moved from codehaus issues that were closed when project was moved to GitHub:
http://jira.codehaus.org/browse/JACKSON-592

When deserializing, it's common for folks to need to unwrap single-component JSON arrays, for downstream handling of the component value. If a feature to enable automagic unwrapping of such arrays were provided, then folks could code mapping solutions as simply as

ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
int number = mapper.readValue("[42]", int.class);

Such configuration could also be available through an annotation. The annotation could be applied to specific properties, or to a class (to effectively apply the annotation to all properties defined in the class).
While the argument that this code

ObjectMapper mapper = new ObjectMapper();
int number = mapper.readValue("[42]", int.class);

sufficiently indicates the author's intentions and provides enough configuration information that ObjectMapper could know what to do – to unwrap [42] to just 42 – I cannot think of any significant benefit to enabling such unwrapping by default. The obvious possible detriment would be breaking existing legacy code.
For consistency, this feature should be applicable to single-component JSON arrays of any primitive, null, object, or array type. So, all of the following examples would work.

String answer = mapper.readValue("[\"is 42\"]", String.class);
boolean trueValue = mapper.readValue("[true]", boolean.class);
Dog dog = mapper.readValue("[{\"name\":\"spike\"}]", Dog.class);
Dog nullReference = mapper.readValue("[null]", Dog.class);

class Dog {public String name;}

The following attempted use of this feature on a JSON array with more than one component should result in a JsonMappingException thrown by the ObjectMapper. (Though, the current error message that "Can not deserialize instance of int out of START_ARRAY token" could be enhanced to recognize the attempt to auto-unwrap the JSON array as if it were a single-component array.)

mapper.readValue("[42,43]", int.class);

For completeness, such a feature could have a serialization counterpart: to wrap a single value into a single-component JSON array.

yinzara added a commit to yinzara/jackson-databind that referenced this issue Jan 8, 2014
Fixes issue FasterXML#381. Added new feature that determines whether it is
acceptable to coerce a single value array (in JSON) to the corresponding
value type.
cowtowncoder added a commit that referenced this issue Jan 10, 2014
@cowtowncoder
Copy link
Member

Implement, as per #384, will be available in 2.4.

@shmosel
Copy link

shmosel commented Nov 23, 2021

Has there been any request to similarly unwrap single-value objects? Seems like it would be very useful and relatively simple to implement.

@yinzara
Copy link
Contributor Author

yinzara commented Nov 23, 2021

In what way are you meaning a "single value object"?

@cowtowncoder
Copy link
Member

lol. "elatively simple to implement.". Right. But yes, as per @yinzara, I am not sure what the request here actually is. An example of JSON, matching POJO would help.

@shmosel
Copy link

shmosel commented Nov 23, 2021

POJO:

class Pojo {
    public int value;
}

JSON:

{
    "value": {
        "anyField": 123
    }
}

Test:

Pojo p = new ObjectMapper()
        .enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_OBJECTS)
        .readValue(json, Pojo.class);
assertEquals(123, p.value);

The implementation would be very similar to array unwrapping:

if (jp.currentToken() == JsonToken.START_OBJECT && ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_OBJECTS)) {
    jp.nextValue();
    int parsed = _parse(jp, ctxt);
    assert jp.nextToken() == JsonToken.END_OBJECT;
    return parsed;
}

@cowtowncoder
Copy link
Member

Ok thank you. I wouldn't be in favor of adding such feature myself, but I understand what is being suggested.

But if you want to propose it and others want (and someone has time to try actual implementation), I'd suggest filing a separate feature request. Closed issues will not be worked on since it gets difficult to track things that get added over time under same issue id.

One other thing: I think there is alternate suggestion of adding something like @JsonWrapped (see #512) which would, I think, work like:

class Pojo {
    @JsonWrapped("anyField")
    public int value;
}

and allow removing/adding intermediate level(s).

@shmosel
Copy link

shmosel commented Nov 23, 2021

It's similar, but not quite the same. If I understand that proposal correctly, it would map to the inverse JSON:

{
    "anyField": {
        "value": 123
    }
}

And of course you'd have to specify the name of the wrapper field.

@cowtowncoder
Copy link
Member

@shmosel Depends on implementation; could be made to work either way. But the idea would be to make it opt-in through property, not a global setting which is bit difficult to make actually work -- assuming many properties do not use such wrapping (so how to distinguish cases where logic needed).

@shmosel
Copy link

shmosel commented Nov 23, 2021

There may not be a property. Consider an array

[
    {
        "anyField": 123
    },
    {
        "anyField": 456
    }
]

It would be useful to have a way to parse this as [123, 456].

@cowtowncoder
Copy link
Member

cowtowncoder commented Nov 23, 2021

I don't quite see why I'd want to do that from modeling perspective but as I said, feel free to file a feature request issue explaining usage etc if you want.
My mention of @JsonWrapped was to make sure you were aware of its existence and whether it'd cover your use case -- sounds like it does not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants