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

JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES does not work for JsonAlias #1851

Closed
pjungermann opened this issue Dec 6, 2017 · 4 comments

Comments

@pjungermann
Copy link

pjungermann commented Dec 6, 2017

I was trying to use @JsonAlias("myAlias") and @JsonFormat(with = {JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES}) at a property at version 2.9.2 (bom) -- current latest jackson-databind version. Unfortunately this failed. Enabling it globally though worked fine. As far as I've checked it, it is related to #1232 which added support for case insensitive properties configured at properties rather than globally and #1029 adding support for @JsonAlias (provided by FasterXML/jackson-annotations#116).

My debugging lead me to the following:

  1. BeanPropertyMap gets created with caseInsensitive = false due to the global configuration at which the alias mapping gets setup case sensitive
  2. BeanPropertyMap.withCaseInsensitivity gets called with the config from JsonFormat
  3. this call creates a new instance of BeanPropertyMap by using the constructor BeanPropertyMap(BeanPropertyMap base, boolean caseInsensitive) which just copies the case sensitive aliasMapping and aliasDef.
  4. BeanPropertyMap.find converts the key to lower case due it being in the case insensitive state. As it does not find the property, it will continue at _find2 by passing _aliasMapping.get(key) to _findWithAlias etc. Neither of those check for the case insensitive state, the key is already in lower case but the mapping is still in it's original case sensitive form.

This leads to that it works only for the property name itself, but not for it's alias names.

@pjungermann
Copy link
Author

pjungermann commented Dec 6, 2017

case 1: annotation at the property

@Data
public class A {
    private B b;
}

@Data
public class B {
    @JsonAlias("propertyAlias")
    @JsonFormat(with = ACCEPT_CASE_INSENSITIVE_PROPERTIES)
    private String property;
}

case 2: annotation at the class level

@Data
public class A {
    private B b;
}

@Data
@JsonFormat(with = ACCEPT_CASE_INSENSITIVE_PROPERTIES)
public class B {
    @JsonAlias("propertyAlias")
    private String property;
}

case 3: annotation at the usage of the class containing the property

@Data
public class A {
    @JsonFormat(with = ACCEPT_CASE_INSENSITIVE_PROPERTIES)
    private B b;
}

@Data
public class B {
    @JsonAlias("propertyAlias")
    private String property;
}

From those 3 variants, only the (3.) one works for me that it actually calls BeanPropertyMap.withCaseInsensitivity to make it case insensitive. For the other two, there seems to be another issue as well. Didn't look much further into it though

@cowtowncoder
Copy link
Member

@pjungermann Thank you for digging deep into this. I'll see how to fix this.

@cowtowncoder
Copy link
Member

Ah. This may be documentation issue.

So, first things first: when used as follows:

public class A {
    @JsonFormat(with = ACCEPT_CASE_INSENSITIVE_PROPERTIES)
    private B b;
}

effects apply to properties of value b, NOT to name b.
Put another way, there is no way specify handling of a single property into case-sensitive/-insensitive; all properties need to be handled the same way. This is due to implementation where lookup map handles distinction for all properties and has no way of passing state on per-property (property name) basis.
Given that there is set semantics here, behavior can not really be changed (although I can see how different meaning could be useful).

So, (1) does not and will not work the way expected here.

(2) on the other hand is probably more like missing handling. It is possible to add per-class config overrides, which do work:

    mapper.configOverride(B.class)
        .setFormat(JsonFormat.Value.empty()
                .withFeature(JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES));

So there may be a missing piece here.

@cowtowncoder
Copy link
Member

Created #1886 as follow up to this, to potentially support (2) in future.

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

2 participants