21

To serialize java objects with camel case attributes to json with underscore we use PropertyNamingStrategy as SNAKE_CASE.

So, is there something to do the opposite as well. That is, deserialise json with underscore to Java objects with camel case.

For example, this JSON:

{
    "user_id": "213sdadl"
    "channel_id": "asd213l"
}

should be deserialised to this Java object:

public class User {
    String userId; // should have value "213sdadl"
    String channelId; // should have value "asd213l"
}

I know one way of doing this which is via @JsonProperty annotation which works at field level. I am interested in knowing any global setting for this.

Ram Patra
  • 16,266
  • 13
  • 66
  • 81
  • 3
    @JLewkovich This isn't exactly a duplicate. Please read the last line of the question. I am not talking about `@JsonProperty` annotation which is the accepted answer there. – Ram Patra Aug 07 '16 at 01:33
  • Actually referred question do have an answer you were probably interested in, look at the highest upvoted one – alex_java_kotlin Jun 06 '17 at 17:38
  • @Quadrat137 yes I have seen the answer, you can also see my comments below the answer. It didn't work both ways for me. That was my question about. – Ram Patra Jun 08 '17 at 10:41

1 Answers1

11

Well, you can have an implementation for PropertyNamingStrategy that looks something like this:

import org.codehaus.jackson.map.MapperConfig;
import org.codehaus.jackson.map.PropertyNamingStrategy;
import org.codehaus.jackson.map.introspect.AnnotatedField;
import org.codehaus.jackson.map.introspect.AnnotatedMethod;

public class CustomNameStrategy extends PropertyNamingStrategy {
    @Override
    public String nameForField(MapperConfig config, AnnotatedField field, String defaultName) {
        return convert(defaultName);
    }

    @Override
    public String nameForGetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) {
        return convert(defaultName);
    }

    @Override
    public String nameForSetterMethod(MapperConfig config, AnnotatedMethod method, String defaultName) {
        return convert(defaultName);
    }

    public String convert(String defaultName) {
        char[] arr = defaultName.toCharArray();
        StringBuilder nameToReturn = new StringBuilder();

        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == '_') {
                nameToReturn.append(Character.toUpperCase(arr[i + 1]));
                i++;
            } else {
                nameToReturn.append(arr[i]);
            }
        }
        return nameToReturn.toString();
    }
}

then in your implementation or the class that does the desrialization you can have:

ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new CustomNameStrategy());
YourClass yourClass = mapper.readValue(yourJsonString, YourClass.class);
Xobotun
  • 1,121
  • 1
  • 18
  • 29
Akintayo Jabar
  • 836
  • 8
  • 13
  • 1
    I am accepting this answer as this is the only solution I got so far and I assume there is no other clean way of doing this. – Ram Patra Aug 07 '16 at 08:11
  • 7
    it is crazy that Jackson uses propertyNamingStrategy for serialisation only – Adam Siemion Jan 27 '19 at 13:23
  • @AdamSiemion for now we can place annotation `@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)` before User class. Now we snake_case json will be automatically translated into camelCase fields. – chill appreciator Apr 18 '20 at 14:40
  • @standalone that does not work with deserialization using latest spring boot stable version (2.5.6) with default configuration – Anddo Nov 15 '21 at 12:01
  • will this work with kotlin data class – lazarus Feb 16 '22 at 06:04