Is there a way to tell Jackson to only ignore a property if it generates XML with annotations?
I have a JPA entity which is exposed via REST (Spring Boot). I'd like to tell Jackson to ignore e.g. the property street when generating XML but not when generating a JSON String
#Entity
public class anObject{
String name;
#JsonIgnore //only when converting to XML? Still need it on a JSON String
String street
//Various Getters, Setters, etc.
}
Thanks in advance!
I presume you have different ObjectMapper for XML and JSON. You can set a mixin annotation only for the XML mapper. E.g.
the mixin annotation :
abstract class anObjectMixIn {
#JsonIgnore String street;
}
the mapper code :
ObjectMapper jsonMapper = new ObjectMapper();
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.addMixIn(anObject.class, anObjectMixIn.class);
And delete the #JsonIgnore over String street. Note how the mixin is only applied on xmlMapper
Jackson allows you tu use JAXB annotations, have a look at the JAXB module.
You can use both Jackson and JAXB together but you can tell which one has priority over the other as mentioned in the documentation, so you can keep your core Jackson annotations for JSON and specialize with JAXB annotations for your XML serialisation.
AnnotationIntrospector primary = new JacksonAnnotationIntrospector();
AnnotationIntrospector secondary = new JaxbAnnotationIntrospector();
AnnotationIntrospector pair = new AnnotationIntrospector.Pair(primaryIntrospector, secondaryIntropsector);
Related
I have some json in a hashmap<string, object> and i’m using ObjectMapper to map it json. I need to change the field names of pretty much all of the values.
ex:
change this
{ “field1”:”abc”, “field2”: “xyz”}
to this
{“f1”:”abc”, “f2”:”xyz”}
I’ve read about using Jackson and using annotation #JsonProperty, but in my case it’s just not feasible because i need to change the names of atleast 20+ fields. What’s the best way to do this?
Why can’t you change ur inout source? Such large change is unnecessary and taxing
If you are parsing this Json with ObjectMapper, after getting intermediate DTO you can apply Mixin and export into String and then convert to required DTO.
Convert String to OriginalDTO with field1
Set Jackson mixin to object mapper
ObjectMapper mapper = new ObjectMapper();
#Getter
#Setter
public abstract class FinalMixin {
#JsonProperty("f1")
private String field1;
}
mapper.addMixInAnnotations(OriginalDTO.class, FinalMixin.class);
Convert DTO that you get in step 1 into String
Convert result String into FinalDTO
When I use an ObjectMapper configured as:
DefaultTyping applicability = ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT;
TypeResolverBuilder<?> typer = DefaultTypeResolverBuilder.construct(applicability, validator);
String propertyName = "type";
typer = typer.init(JsonTypeInfo.Id.NAME, null);
typer = typer.inclusion(JsonTypeInfo.As.PROPERTY);
typer = typer.typeProperty(propertyName);
ObjectMapper mapper=new ObjectMapper();
mapper.setDefaultTyping(typer);
It produces JSON like:
{
"type": "ShortClassName",
...
}
The type does not have the full package name as expected. However trying to deserialize using this object mapper cause:
com.fasterxml.jackson.databind.exc.InvalidTypeIdException
How do I specify the base package name as part of the object mapper configuration so that the serialized JSON only has the classname?
You can create a mapper for a specific Object by using mapper.readerFor(...) and specifying which type to extract, in this case this would be
ObjectReader shortClassNameReader = mapper.readerFor(new TypeReference<ShortClassName>(){})
Where ShortClassName is your class's name.
Then you can use this ObjectReader with readValue to deserialize the JSON.
Thanks Ayk - your solution works if the class name is itself the one to be deserialized but if it is nested inside the JSON for another class, it does not work. However I got it working by defining a custom typeIdResolver that translates the ID from/to object in idFromValue and typeFromId respectively. This then works globally without the need for annotation on each object involved in the serialization.
I have a POJO object that has UpperCamelCase naming. When I do the call to Jackson's ObjectMapper to serialize/marshal it to JSON, the result is lowerCamelCase for field names.
The call is now trivial:
Heading
ObjectMapper objectMapper = new ObjectMapper();
jsonText = objectMapper.writeValueAsString(myObjectToJson);
how I can tell ObjectMapper to make UpperCamelCase? Or is it some sort of set-in-stone JSON standard?
I use jackson inside Apache Camel.
edited original answer.
Jackson uses camelCasing as default it seems. They have implemented a PascalCasing strategy. Try this:
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.PASCAL_CASE_TO_CAMEL_CASE);
Or annotate your fields with #JsonProperty("UpperCaseProperty")
My pojo class is annotated with XmlAccessorType.NONE.
#XmlRootElement
#XmlAccessorType(XmlAccessType.NONE)
public class Human {
#XmlElement(name="name")
private String name;
private int age
}
JSON which im trying to read contains both properties name and age. If i annotate the class with JsonIgnoreProperties(ignoreUnknown = true) everything works However if i try to use annotation XmlAccessorType(XmlAccessType.NONE) intead, jackson throws unknown property exception.
I tried to add JaxbAnnotationIntrospector into objectmapper but it did not help mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector());
I don't see why XmlAccessorType(XmlAccessType.NONE) would be relevant here,
It would affect discovery of properties available (no auto-discovery), but NOT what to do with JSON/XML properties for which there is no Bean property.
The difference here is probably more due to difference between defaults for JAXB and Jackson: by default, JAXB silently ignores anything it does not recognize. By default Jackson throws an exception when it does not recognize something.
If you want, you can configure ObjectMapper to ignore these problems by default:
napper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
so that behavior is similar to that of JAXB.
The rest service responds with
<transaction><trxNumber>1243654</trxNumber><type>INVOICE</type></transaction>
or in JSON:
{"transaction":{"trxNumber":1243654,"type":"INVOICE"}}
There is no problems when I use:
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true)
And as resulting class
#JsonRootName("transaction")
public class Transaction {
private String trxNumber;
private String type;
//getters and setters
}
But actually I should use the Transaction class from 3rd party jar, which is exact like above, but has no #JsonRootName("transaction") annotation.
So I end up with
Could not read JSON: Root name 'transaction' does not match expected ('Transaction') for type...
Is there any ways to force Jackson parse to Transaction class without adding any stuff to the Transaction class itself (as I get this file as part of a binary jar)?
I've tried custom PropertyNamingStrategy, but it seems has to do only with field and getter/setter names, but not class names.
Java7, Jackson 2.0.5.
Any suggestions? thanks.
You can do it with mixin feature. You can create simple interface/abstract class like this:
#JsonRootName("transaction")
interface TransactionMixIn {
}
Now, you have to configure ObjectMapper object:
ObjectMapper mapper = new ObjectMapper();
mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
mapper.addMixInAnnotations(Transaction.class, TransactionMixIn.class);
And finally you can use it to deserialize JSON:
mapper.readValue(json, Transaction.class);
Second option - you can write custom deserializer for Transaction class.