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

Distinguish null from empty string for UUID deserialization #2066

Closed
leonshaw opened this issue Jun 15, 2018 · 8 comments
Closed

Distinguish null from empty string for UUID deserialization #2066

leonshaw opened this issue Jun 15, 2018 · 8 comments
Assignees
Labels
coercion-config Issue related to 2.12 added "CoercionConfig"
Milestone

Comments

@leonshaw
Copy link

For UUID deserialization, empty string is mapped to null by FromStringDeserializer. So something like {"parent_uuid": null} can't be distinguished from {"parent_uuid": ""}. From the view of a strict API, the latter is an error.
It would be good to add some feature like "STRICT_STRING_VALUE", that FromStringDeserializer does not trim or shortcut empty strings so that UUID deserializer could report the error.
This may be an opposite feature of #768 ACCEPT_EMPTY_STRING_AS_NULL_OBJECT.

@cowtowncoder
Copy link
Member

Ok. What do you think would make most sense for empty String in strict mode? Exception would seem like my first choice, although there is also the"empty" UUID, which you'd get from "all zeroes".

It would also be possible to consider MapperFeature.ALLOW_COERCION_OF_SCALARS here: disabling of which could prevent use of empty String... also semantically there is the question of whether this really is coercion.

Now: from practical perspective, behavior change can not be made in 2.9 patch versions, since it would likely break some processing somewhere (even if behavior for default settings was unchanged, unless new feature was added, which in turn should not be done in a patch).
On plus side I am planning to do one more 2.x, 2.10, so this could get in.

@leonshaw
Copy link
Author

I prefer to throw exception. All-zero UUIDs should be supplied explicitly, to be "strict".
I think it's different from coercion. Because string is already the representation of UUID, it's just normal parsing and there's nothing special of empty string than any arbitrary strings.
Good to hear it could go in 2.10. Thanks.

@cowtowncoder cowtowncoder added good first issue Issue that seems easy to resolve and is likely a good candidate for contributors new to project and removed 2.10 labels Apr 2, 2020
@cowtowncoder
Copy link
Member

So: there is @JsonFormat(lenient=OptBoolean.FALSE) (and matching config override), so I think that should be the mechanism. Will see if I have time to actually work on this.

@shahaf-sameach
Copy link

hi, new contributor :) can I try this one?

@cowtowncoder
Copy link
Member

@shahaf-sameach Absolutely! Trickiest part might just be figuring out how to get information on all parts of leniency settings: sources at less src/main/java/com/fasterxml/jackson/databind/deser/std/DateDeserializers.java seem to be main reference at this point.

To be more exact, there are 3 levels of leniency settings:

  1. ObjectMapper.setDefaultLenience(Boolean) (default is effectively Boolean.TRUE)
  2. Per-type config overrides: mapper.configOverride(UUID.class).setFormat(....)
  3. Per-property override with @JsonFormat annotation

so the trick is to figure out combination of effective setting. An example can be found from DateDeserializers class I mention above:

        @Override
        public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
                BeanProperty property)
           throws JsonMappingException
        {
            final JsonFormat.Value format = findFormatOverrides(ctxt, property,
                    handledType());

            if (format != null) {
...
}

so you would add this method in UUIDDeserializer to allow for changing setting (and boolean field in UUIDDeserializer itself to keep track).

And then finally, tests to verify that new handling works. Place to add tests would be

src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKStringLikeTypesTest.java

I hope this helps!

cowtowncoder added a commit that referenced this issue May 8, 2020
@cowtowncoder cowtowncoder added 2.12 and removed good first issue Issue that seems easy to resolve and is likely a good candidate for contributors new to project labels May 23, 2020
@cowtowncoder
Copy link
Member

I am thinking of actually tackling this as part of much bigger change -- #2728 -- and removing "good first issue" tag since approach I proposed here is not needed.

@cowtowncoder
Copy link
Member

I will start working on this issue, based on new CoercionConfigs feature (as mentioned above).

@cowtowncoder cowtowncoder self-assigned this Jun 4, 2020
@cowtowncoder cowtowncoder added android Issues related to use on Android platform coercion-config Issue related to 2.12 added "CoercionConfig" and removed android Issues related to use on Android platform labels Jun 8, 2020
@cowtowncoder cowtowncoder added this to the 2.12.0 milestone Jun 10, 2020
@cowtowncoder
Copy link
Member

cowtowncoder commented Jun 10, 2020

So, implemented using new "CoercionConfigs" system; test CoerceMiscScalarsTest has full verification for UUID as well as other types. Default behavior in 2.12 NOT changed.

To make coercion from empty String fail only for UUID, you can use:

ObjectMapper mapper = ...;
mapper.coercionConfigFor(UUID.class)
    .setCoercion(CoercionInputShape.EmptyString, CoercionAction.Fail);

or to change handling of most similar scalar types:

ObjectMapper mapper = ...;
mapper.coercionConfigFor(LogicalType.OtherScalar)
    .setCoercion(CoercionInputShape.EmptyString, CoercionAction.Fail);

or, even, if you really want, prevent it by most types (unless overridden by more-specific setting:

ObjectMapper mapper = ...;
mapper.coercionConfigDefaults()
    .setCoercion(CoercionInputShape.EmptyString, CoercionAction.Fail);

Alternatively you can use CoercionAction.AsNull to allow coercion to null, or, CoercionAction.AsEmpty to get "all-zeroes" UUID constructed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
coercion-config Issue related to 2.12 added "CoercionConfig"
Projects
None yet
Development

No branches or pull requests

3 participants