22

I think I need to create a specialist ObjectMapper and cannot find any sample code to start the process.

The creator of the JSON is using .Net and public properties and therefore uses field names with an uppercase initial. I am parsing the JSON into POJOs so I would like to use a lowercase initial.

At their end:

    public class Facet
    {
        public string Name { get; set; }
        public string  Value { get; set; }
    }

At my end I must therefore have:

    public class Facet {
        public String Name;
        public String Value;
    }

I would much prefer:

    public class Facet {
        public String name;
        public String value;
    }

Am I right that this could be done with an ObjectMapper?

OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
  • 1
    I have retitled and removed the second part of the question. The other half is posted [here](http://stackoverflow.com/q/12450404/823393) – OldCurmudgeon Sep 16 '12 at 20:22

5 Answers5

28

Your first issue can be addressed very simply with the @JsonProperty annotation:

// java-side class
public class Facet
{
    @JsonProperty("Name")
    public String name;

    @JsonProperty("Value")
    public String value;
}

Now the ObjectMapper will match up the differently-cased field names. If you don't want to add annotations into your classes, you can create a Mix-in class to stand in for your Facet:

public class FacetMixIn
{
    @JsonProperty("Name")
    public String name;

    @JsonProperty("Value")
    public String value;
}

objectMapper.getDeserializationConfig().addMixInAnnotations(Facet.class, FacetMixIn.class);

This will achieve the same thing, without requiring additional annotations in your Facet class.

pb2q
  • 58,613
  • 19
  • 146
  • 147
  • That's exactly what I was looking for in part 1 :) Thanks. I have added to part 2. Does that make it easier? – OldCurmudgeon Sep 15 '12 at 17:20
  • I've split the original question into two now so this is now a complete answer. By all means modify to reflect the change in the question. – OldCurmudgeon Sep 16 '12 at 20:23
  • Wow. If I could multi-upvote this I would. I have wasted close to a full day just this week on JSON mapping issues caused by APIs that use leading uppercase on *some* parameters. Once I figured out that was the cause these annotations are a perfect fix. – Brian Knoblauch Jun 08 '18 at 20:28
  • @BrianKnoblauch really glad to have helped another dev – pb2q Jun 08 '18 at 22:13
  • From jackson 2.5 onwards you can add mixin simply like - `objectMapper.addMixIn(Facet.class, FacetMixIn.class)` – Manthan Jamdagni May 22 '20 at 14:55
15

Instead of annotating each field, the Jackson ObjectMapper can be configured to use a built-in or custom PropertyNamingStrategy, to apply a consistent translation between Java property/field names and JSON element names.

For example:

myObjectMapper.setPropertyNamingStrategy(PascalCaseStrategy);
Programmer Bruce
  • 64,977
  • 7
  • 99
  • 97
  • Thanks @ProgrammerBruce for your further help. I will check this works when I get back to work later in the new year. BTW - is there a strategy that will match ANY case? If no, perhaps you could post one. I am trying to deal with a customer who could change their conventions at any time. – OldCurmudgeon Jan 03 '13 at 02:24
  • Last I looked (a year or so ago), name translations only go in one direction (either from Java property/field names to JSON element names, or vice versa), and so implementing case-insensitive matching wasn't as trivial as it otherwise could be. – Programmer Bruce Jan 04 '13 at 03:48
  • @Jose: They're different things. SnakeCaseStrategy is for "snake_case_variables" – dagnelies Mar 11 '16 at 14:49
  • @arnaud indeed, sorry about that. – Jose Alban Mar 11 '16 at 15:17
8

This problem could be solved from Jackson 2.5.0 like this:

ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);

From the javadoc:

com.fasterxml.jackson.databind.MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES

Feature that will allow for more forgiving deserialization of incoming JSON. If enabled, the bean properties will be matched using their lower-case equivalents, meaning that any case-combination (incoming and matching names are canonicalized by lower-casing) should work.

Note that there is additional performance overhead since incoming property names need to be lower-cased before comparison, for cases where there are upper-case letters. Overhead for names that are already lower-case should be negligible however.

Feature is disabled by default.

Since: 2.5

madx
  • 6,723
  • 4
  • 55
  • 59
  • Has anyone compared the performance difference against using the annotations? The annotations feel safer, but after talking to other JSON users (other languages), this here option (case insensitive) seems to be the normal expected behaviour... Jackson seems to be the oddball by being strict about casing. – Brian Knoblauch Jun 08 '18 at 22:46
0

Just a quick update as I was looking for same answer and a code snippet objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

dekay
  • 1
  • 1
  • This should be a comment. If you do not yet have enough rep to comment yet then thank you for your contribution but when you do, please delete this answer and post a comment. – OldCurmudgeon May 02 '19 at 05:14
0

Since v 2.13 use builder:

XmlMapper xmlMapper = (XmlMapper) getObjectMapper();

private ObjectMapper getObjectMapper() {
    return XmlMapper.builder()
        .configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true)
        .build();
}
6rzes
  • 11
  • 1
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 06 '22 at 09:20