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

Java Bean naming conventions not respected for boolean properties -> Incompatibility with standard Jackson ObjectMapper #291

Closed
prismec opened this issue Oct 21, 2016 · 8 comments

Comments

@prismec
Copy link

prismec commented Oct 21, 2016

If the field name of a boolean Java Bean Property differs from the name of the getters and setters and starts with "is" it is serialized wrong. This does not follow bean naming conventions and is incompatible with an ObjectMapper used without the Scala module. Here's a Spock specification to show the problem (the second test may occasionally fail due to ordering of properties):

package smarter.ecommerce.whoop

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.datatype.joda.JodaModule
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import spock.lang.Specification

public class JacksonSerializationIssue extends Specification {

static class Bean {
    private boolean isBooleanProperty = true;
    private boolean nameDoesNotMatter = false;
    private String isString = "value";

    public boolean isBooleanProperty() {
        return isBooleanProperty;
    }

    public void setBooleanProperty(boolean booleanProperty) {
        this.isBooleanProperty = booleanProperty;
    }

    public boolean getAnotherBooleanProperty() {
        return nameDoesNotMatter;
    }

    public void setAnotherBooleanProperty(boolean anotherBooleanProperty) {
        this.nameDoesNotMatter = anotherBooleanProperty;
    }

    public String getString() {
        return isString;
    }

    public void setString(String isString) {
        this.isString = isString;
    }
}

def "serialize to JSON with scala module"() {
    def objectMapper = new ObjectMapper().registerModule(new DefaultScalaModule())

    expect:
    objectMapper.writeValueAsString(new Bean()) == """{"booleanProperty":true,"anotherBooleanProperty":false,"string":"value"}"""
}

def "serialize to JSON without scala module"() {
    def objectMapper = new ObjectMapper()

    expect:
    objectMapper.writeValueAsString(new Bean()) == """{"string":"value","booleanProperty":true,"anotherBooleanProperty":false}"""
}
}
@rajendrag
Copy link

Is there any solution for this?

@pjfanning
Copy link
Member

My understanding is that Java reflection does not give deterministic ordering of parameters. And JSON parsers generally don't care too much about the order of the parameters.

If someone wants to submit a patch, feel free but I'm not planning to prioritise work on this.

@cowtowncoder
Copy link
Member

I think there may be two different issues: one is that test itself is bit fragile as order of properties is not specified and (as @pjfanning correctly points out) order of fields, methods is not guaranteed to be declaration order. For repeatable tests it should be necessary to either force ordering (using @JsonPropertyOrder, for example; or by enabling MapperFeature.SORT_PROPERTIES_ALPHABETICALLY), or to make test allow any ordering (bind to MaporJsonNode`, check logical contents).

The other one, main question I assume, is whether logical property discovery should vary between default databind and Scala module: it seems that there is difference, possibly unintentional one?
I know there were issues with Kotlin module in same area, although there Kotlin's bean naming is actually different than Java's, so it may not be exactly the same issue.

@pjfanning
Copy link
Member

#455 might help - scheduled for 2.12.0 release. If you have time, try out 2.12.0-SNAPSHOT.

@rajendrag
Copy link

Yes, they are two different issues. What I assumed this ticket talking about is, after adding DefaultScalaModule the boolean properties are serialized by removing "is" from the name. Example: isBooleanProp is serialised to "booleanProp" instead of "isBooleanProp".

@pjfanning I tried to test it with 2.12 SNAPSHOT but could not find jackson-module-scala_2.13 in sonatype repo.

@pjfanning
Copy link
Member

https://oss.sonatype.org/content/repositories/snapshots/com/fasterxml/jackson/module/jackson-module-scala_2.13/2.12.0-SNAPSHOT/ -- if you use sbt, add this to build.sbt

resolvers += Resolver.sonatypeRepo("snapshots")

@rajendrag
Copy link

Observed the same problem with 2.12 as well. The private boolean isBooleanProperty is being serialized to booleanProperty instead of isBooleanProperty.

@pjfanning
Copy link
Member

I am closing this - 3f3e818 seems to indicate that this works in jackson 2.12.x and above.

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

4 participants