Jackson overcoming underscores in favor of camel-case
You should use the @JsonProperty
on the field you want to change the default name mapping.
class User{
@JsonProperty("first_name")
protected String firstName;
protected String getFirstName(){return firstName;}
}
For more info: the API
Deserialising JSON with underscores to camel case in Java using Jackson?
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);
Not able to convert underscore case to camel case with Jackson
Always respect the Java naming conventions in your Java code. Use annotations to deal with Json not respecting them.
In this case, use JsonAlias
Annotation that can be used to define one or more alternative names for a property, accepted during deserialization as alternative to the official name
public class WPPostResponse {
@JsonAlias("featured_media")
Long featuredMedia;
public Long getFeaturedMedia() {
return featuredMedia;
}
public void setFeaturedMedia(Long featuredMedia) {
this.featuredMedia = featuredMedia;
}
}
Stop Jackson from changing case of variable names
The problem here is more about JavaBeans(TM) Specification. According to the spec (page 58)
However to support the occasional use of all upper-case names, we
check if the first two characters of the name are both upper case and
if so leave it alone“FooBah” becomes “fooBah”
“Z” becomes “z”
“URL” becomes “URL”
And you have an edge case with aName
field . Because if the getter looks like AName()
, then when you convert back from this getter you should look for AName
field according to the specification. Here is additional info explanation
So to fix this, you can use a proper getter(getaName()
) or @JsonProperty("aName")
annotation above field/getter
Here is similar question
Why does Jackson 2 not recognize the first capital letter if the leading camel case word is only a single letter long?
The problem you are seeing is due to the fact that Jackson uses Java Bean naming conventions to figure out the the Json properties in a Java class.
Here is a reference of the specific problem you see, the recommendation is not to capitalize either of the first two letters in your field. If you use an IDE like IntelliJ or eclipse and let the IDE generate the setters for you, you will notice the same "behavior" occurs, you will end up with the following methods:
public void setaLogId(String aLogId) {
this.aLogId = aLogId;
}
public String getaLogId() {
return aLogId;
}
Hence, when you change the "L" to lower case Jackson was able to figure it out the field you wanted to map.
Having said the above, you still have the alternative to use the "aLogId" field name and make Jackson work all you have to do is use the @JsonProperty
annotation with the aLogId
in it.
@JsonProperty("aLogId")
private String aLogId;
The following test code is to show how this will work:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Test {
@JsonProperty("aLogId")
private String aLogId;
public void setaLogId(String aLogId) {
this.aLogId = aLogId;
}
public String getaLogId() {
return aLogId;
}
public static void main(String[] args) {
ObjectMapper objectMapper = new ObjectMapper();
Test test = new Test();
test.setaLogId("anId");
try {
System.out.println("Serialization test: " + objectMapper.writeValueAsString(test));
String json = "{\"aLogId\":\"anotherId\"}";
Test anotherTest = objectMapper.readValue(json, Test.class);
System.out.println("Deserialization test: " +anotherTest.getaLogId());
} catch (Exception e) {
e.printStackTrace();
}
}
}
The output of the test is:
Serialization test: {"aLogId":"anId"}
Deserialization test: anotherId
How to convert camel case to lower case with underscores in a REST API?
If you want to make this behaviour the default one, you have to configure this in the object mapper that is responsible for serialization/deserialization of objects to json.
In Quarkus, you can use either Jackson or JsonB for object mapping.
For Jackson, you can control the behaviour of field names using PropertyNamingStrategy which you want to set to SNAKE_CASE
. To set this globally, create an ObjectMapperCustomizer
like so:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import io.quarkus.jackson.ObjectMapperCustomizer;
import javax.inject.Singleton;
@Singleton
public class ObjectMapperConfig implements ObjectMapperCustomizer {
@Override
public void customize(ObjectMapper objectMapper) {
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
}
}
You can control many more aspects of serialization e.g. ignore unknown props during deserialization, date formatting, etc.
You need to have a dep to quarkus-resteasy-jackson
:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>
If you want to use JsonB (quarkus-resteasy-jsonb
) then you can try it with the following JsonbConfigCustomizer
import io.quarkus.jsonb.JsonbConfigCustomizer;
import javax.inject.Singleton;
import javax.json.bind.JsonbConfig;
import javax.json.bind.config.PropertyNamingStrategy;
@Singleton
public class JsonBCustomizer implements JsonbConfigCustomizer {
public void customize(JsonbConfig config) {
config.withPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE_WITH_UNDERSCORES);
}
}
Set naming strategy to lower camel case for one class
To enforce lowerCamelCase, you can use the annotation
@JsonNaming(PropertyNamingStrategy::class)
This enforces the default naming strategy (lowerCamelCase) and overrides a globally configured naming strategy.
Jersey JSON switching from camel case to underscores (snake case)
This is something that needs to be configured with the Jackson ObjectMapper
. You can do this in a ContextResolver
. Basically, you need something like
@Provider
public class MapperProvider implements ContextResolver<ObjectMapper> {
final ObjectMapper mapper;
public MapperProvider() {
mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(
PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
}
@Override
public ObjectMapper getContext(Class<?> cls) {
return mapper;
}
}
Then register with your client
client.register(MapperProvider.class);
If you need this support on the server also, then you will need to register it on the server too.
Related Topics
Encrypt and Decrypt with Aes and Base64 Encoding
Why Isn't a Qualified Static Final Variable Allowed in a Static Initialization Block
How to Compile a Java Source File Which Is Encoded as "Utf-8"
This: Cannot Use This in Static Context
How to Check If a Date Object Equals Yesterday
How to Read a File from a Certain Offset in Java
Boolean Expression Parser in Java
Java - Removing First Character of a String
How to Change My Windows Desktop Wallpaper Programmatically in Java/Groovy
How to Test If My Font Is Rendered Correctly in PDF
Why Does Autoreconnect=True Not Seem to Work
Throw Checked Exceptions from Mocks with Mockito
Error:Java: Invalid Source Release: 8 in Intellij. What Does It Mean
No Exception While Type Casting with a Null in Java
How to Enable Commit on Focuslost for Tableview/Treetableview