http://stackoverflow.com/questions/6526911/best-way-to-compare-2-json-files-in-java
When we try to serialize an instance of “Item“, Jackson will throw a JsonMappingException exception:
This might happen if you have two different instances of your class that have the same id. This would be something that you would have to fix in your code outside of what you have provided
https://github.com/FasterXML/jackson-databind/issues/266
https://github.com/jsog/jsog-jackson
https://github.com/jsog/jsog
http://stackoverflow.com/questions/11664894/jackson-deserialize-using-generic-class
no String-argument constructor/factory method to deserialize from String value
http://stackoverflow.com/questions/24397647/jersey-exception-mappers-not-working-when-jackson-deserialization-fails
https://github.com/jersey/jersey/blob/master/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/JacksonFeature.java
https://www.javacodegeeks.com/2013/04/how-to-use-propertynamingstrategy-in-jackson.html
https://blog.layer4.fr/2013/08/19/how-to-map-unknown-json-properties-with-jackson/
http://www.cowtowncoder.com/blog/archives/2011/07/entry_458.html
Thread-safe and performance
http://wiki.fasterxml.com/JacksonBestPracticesPerformance
http://wiki.fasterxml.com/ObjectReader
https://theartofdev.com/2014/07/20/jackson-objectmapper-performance-pitfall/
It raised my suspicion as everywhere else we use ObjectMapper as a static field so only a single instance is created.
After making a little tester (simplified version can be found below) I discovered that the using instance vs. static ObjectMapper field result in approximately x20 performance difference, that is the instance field usage is 20 times slower than static field!
Changing the ObjectMapper to static and re-running the test confirmed the issue, performance was significantly improved and the most expensive method became Proxy.newProxyInstance.
I can speculate that ObjectMapper uses reflection to create the POJO type from the string value, at least to find the constructor annotated with @JsonCreator. To improve performance ObjectMapper keeps some kind of caching per instance so creating a new instance each time requires ObjectMapper to do the expensive work each time.
http://wiki.fasterxml.com/JacksonFeaturesNonStandard
http://wiki.fasterxml.com/JacksonFAQThreadSafety
http://stackoverflow.com/questions/18611565/how-do-i-correctly-reuse-jackson-objectmapper
http://fasterxml.github.io/jackson-databind/javadoc/2.1.0/com/fasterxml/jackson/databind/ObjectReader.html
Builder object that can be used for per-serialization configuration of deserialization parameters, such as root type to use or object to update (instead of constructing new instance).
https://dzone.com/articles/how-serialize-javautildate
http://wiki.fasterxml.com/JacksonPolymorphicDeserialization
fixing recursive relationship issues with mixins
@JsonFilter("thing filter")
public class ThingMixin {
}
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Thing.class, ThingMixin.class);
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("thing filter", SimpleBeanPropertyFilter.serializeAllExcept("user"));
mapper.setFilters(filterProvider);
fixing classes that don't conform to the bean spec with modules and customer serializers
public class WidgetNameSerializer extends JsonSerializer<WidgetName> {
@Override
public void serialize(WidgetName widgetName, JsonGenerator jgen, SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeString(widgetName.value());
}
}
http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html
https://github.com/PressAssociation/partial-response/tree/master/filter-json-jackson
https://jira.spring.io/browse/SPR-7156
http://javaactive.blogspot.com/2014/05/how-to-implement-jackson-filters-to.html
http://www.baeldung.com/jackson-serialize-field-custom-criteria
http://www.jroller.com/RickHigh/entry/filtering_json_feeds_from_spring
Using Jackson to (De)-serialize a Scala Case Class
https://www.mkyong.com/java/jackson-streaming-api-to-read-and-write-json/
Jackson supports read and write JSON via high-performance Jackson Streaming APIs, or incremental mode.
JsonSerializer - SerializerProvider serializer
serializer.defaultSerializeValue(oct, jGen);
https://dzone.com/articles/latest-jackson-integration
Jackson2ObjectMapperBuilder
http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html
USE_ANNOTATIONS(true),
How to ignore pojo annotations while using Jackson ObjectMapper?
http://stackoverflow.com/questions/31680046/how-to-ignore-pojo-annotations-while-using-jackson-objectmapper
ObjectMapper objectMapper = new ObjectMapper().configure(
org.codehaus.jackson.map.DeserializationConfig.Feature.USE_ANNOTATIONS, false) .configure(org.codehaus.jackson.map.SerializationConfig.Feature.USE_ANNOTATIONS, false);
http://www.baeldung.com/jackson-ignore-properties-on-serialization
@JsonProperty("anotherName")
@JsonIgnoreProperties(value = { "someField" })
@JsonIgnore
@JsonIgnoreType
public class SomeType { ... }
http://www.baeldung.com/jackson-exception
Jackson will serialize the Date to a timestamp format by default (number of milliseconds since January 1st, 1970, UTC).
http://www.leveluplunch.com/java/tutorials/033-custom-jackson-date-deserializer/
https://github.com/FasterXML/jackson-datatype-guava
How to enable pretty print JSON output (Jackson)
http://www.baeldung.com/jackson-ignore-properties-on-serialization
5. Ignore fields using Filters
http://www.cowtowncoder.com/blog/archives/2011/02/entry_443.html
By default all properties without explicit view definition are included in serialization.
http://stackoverflow.com/questions/16089651/jackson-serialization-ignore-empty-values-or-null
Jackson allows controlling this behavior at either the class level or field level.
Good catch regarding
you can NOT change settings by accessing an instance and calling methods:
http://stackoverflow.com/questions/18043587/why-im-not-able-to-unwrapp-and-serialize-java-map-using-jackson-java-library
http://wiki.fasterxml.com/JacksonFeatureAnyGetter
Jersey Client with Customize JSON (Jackson) Configuration
https://dzone.com/articles/custom-json-deserialization-with-jackson
http://wiki.fasterxml.com/JacksonFeatureUnwrapping
http://stackoverflow.com/questions/20563640/using-jackson-objectmapper-with-jersey
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@Type(value = Cat.class, name = "cat"),
@Type(value = Dog.class, name = "dog") })
http://www.mkyong.com/java/how-to-convert-java-map-to-from-json-jackson/
List<MyObject> readValue = mapper.readValue(jsonString, collectionType);
http://www.baeldung.com/jackson-collection-array
MyDto class needs to have the no-args default constructor – if it doesn’t, Jackson will not be able to instantiate it:
http://tutorials.jenkov.com/java-json/jackson-annotations.html
http://tutorials.jenkov.com/java-json/jackson-objectmapper.html
CSV
https://github.com/FasterXML/jackson-dataformat-csv
http://blog.xyleolabs.com/2015/05/making-your-jersey-client-post-csv-data.html
http://stackoverflow.com/questions/31685653/spring-boot-jersey-jackson/31703546#31703546
http://stackoverflow.com/questions/21787128/how-to-unit-test-jackson-jsonserializer-and-jsondeserializer
This only addresses equality, not differences.
ObjectMapper mapper = new ObjectMapper();
JsonNode tree1 = mapper.readTree(jsonInput1);
JsonNode tree2 = mapper.readTree(jsonInput2);
boolean areTheyEqual = tree1.equals(tree2);
http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion
The “User” entity:
1
2
3
4
5
| public class User { public int id; public String name; public List<Item> userItems; } |
The “Item” entity:
1
2
3
4
5
| public class Item { public int id; public String itemName; public User owner; } |
com.fasterxml.jackson.databind.JsonMappingException:
Infinite recursion (StackOverflowError)
(through reference chain:
org.baeldung.jackson.bidirection.Item[
"owner"
]
->org.baeldung.jackson.bidirection.User[
"userItems"
]
->java.util.ArrayList[0]
->org.baeldung.jackson.bidirection.Item[
"owner"
]
->…..
- @JsonManagedReference is the forward part of reference – the one that gets serialized normally.
- @JsonBackReference is the back part of reference – it will be omitted from serialization.
1
2
3
4
| @JsonIdentityInfo ( generator = ObjectIdGenerators.PropertyGenerator. class , property = "id" ) public class User { ... } |
And to the “Item” entity:
1
2
3
4
| @JsonIdentityInfo ( generator = ObjectIdGenerators.PropertyGenerator. class , property = "id" ) public class Item { ... } |
https://github.com/FasterXML/jackson-databind/issues/266
@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class,property="@id", scope=OwnerScope.class) public User owner; @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class,property="@id", scope=UserScope.class) public User user;
https://github.com/jsog/jsog-jackson
https://github.com/jsog/jsog
http://stackoverflow.com/questions/11664894/jackson-deserialize-using-generic-class
JavaType type = mapper.getTypeFactory().constructParametricType(Data.class, contentClass.class);
return mapper.readValue(json, type);
http://stackoverflow.com/questions/40166309/no-string-argument-constructor-factory-method-to-deserialize-from-string-valueno String-argument constructor/factory method to deserialize from String value
"multimedia" field is an empty string
So you need to verify your json and map you pojo accordingly.
http://stackoverflow.com/questions/24397647/jersey-exception-mappers-not-working-when-jackson-deserialization-fails
But there is one case in which neither my Exception mappers nor my json producing jsp are working, that is when sending a bad formed json to a POST REST endpoint which just returns the following message:
Can not deserialize instance of com.example.rest.User[] out of START_OBJECT token
at [Source: org.glassfish.jersey.message.internal.EntityInputStream@1dcccac; line: 1, column: 1]
Update: changed JsonParseException to JsonProcessingException (more general)
Update2: In order to avoid registering the unwanted mappers replace
register(org.glassfish.jersey.jackson.JacksonFeature.class);
with
register(com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider.class);
Look at the source code of JacksonFeature and you'll understand what's happening.
https://www.javacodegeeks.com/2013/04/how-to-use-propertynamingstrategy-in-jackson.html
https://blog.layer4.fr/2013/08/19/how-to-map-unknown-json-properties-with-jackson/
@JsonAnySetter is a simple marker that can be used to define a two-argument method (first argument name of property, second value to set), to be used as a “fallback” handler for all otherwise unrecognized properties found from JSON content.
http://stackoverflow.com/questions/10079617/handling-alternate-property-names-in-jackson-deserializationObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
http://stackoverflow.com/questions/8560348/different-names-of-json-property-during-serialization-and-deserializationpublic class Coordinates {
byte red;
@JsonProperty("r")
public byte getR() {
return red;
}
@JsonProperty("red")
public void setRed(byte red) {
this.red = red;
}
}
The idea is that method names should be different, so jackson parses it as different fields, not as one field.
Here is test code:
Coordinates c = new Coordinates();
c.setRed((byte) 5);
ObjectMapper mapper = new ObjectMapper();
System.out.println("Serialization: " + mapper.writeValueAsString(c));
Coordinates r = mapper.readValue("{\"red\":25}",Coordinates.class);
System.out.println("Deserialization: " + r.getR());
http://www.cowtowncoder.com/blog/archives/2011/07/entry_458.html
Thread-safe and performance
http://wiki.fasterxml.com/JacksonBestPracticesPerformance
http://wiki.fasterxml.com/ObjectReader
https://theartofdev.com/2014/07/20/jackson-objectmapper-performance-pitfall/
It raised my suspicion as everywhere else we use ObjectMapper as a static field so only a single instance is created.
After making a little tester (simplified version can be found below) I discovered that the using instance vs. static ObjectMapper field result in approximately x20 performance difference, that is the instance field usage is 20 times slower than static field!
Changing the ObjectMapper to static and re-running the test confirmed the issue, performance was significantly improved and the most expensive method became Proxy.newProxyInstance.
I can speculate that ObjectMapper uses reflection to create the POJO type from the string value, at least to find the constructor annotated with @JsonCreator. To improve performance ObjectMapper keeps some kind of caching per instance so creating a new instance each time requires ObjectMapper to do the expensive work each time.
http://wiki.fasterxml.com/JacksonFeaturesNonStandard
7. Prefer ObjectReader/ObjectWriter over ObjectMapper
Although the main reason to prefer these objects is thread-safety (and thus correctness), there may be performance benefits as well. Latest Jackson versions (2.1 and above) will be able to reuse root-level (de)serializers, making reuse of ObjectReaders and ObjectWriters bit more efficient than using ObjectMapper.
http://wiki.fasterxml.com/JacksonFAQThreadSafety
The basic rule of Jackson thread-safety is that factories follow "thread-safe after configuration" philosophy. This means that:
- Configuring an instance is not synchronized or thread-safe, i.e. do not change settings while using it (which makes sense for other reasons too -- not all settings take effect once mapper has been in use, due to caching of serializers and deserializers)
- Once configuration is complete, operation is fully thread-safe and synchronized in few places where that is needed, for symbol table and buffer reuse.
So as long as you first configure such factories from a single thread, and only then use it (from any number of threads), usage will be thread-safe without additional synchronization.
This rule specifically is used for:
- ObjectMapper (and sub-classes)
- JsonFactory (and sub-classes, like SmileFactory)
Note that more recently some new factory-like classes use "Fluent" pattern, whereby instances are immutable (and thus fully thread-safe!), and differently configured instances are constructed by factory methods. Specifically:
- ObjectReader and ObjectWriter instances are immutable and thread-safe: they are created by ObjectMapper, and once constructed, their state NEVER CHANGES. To get instance with different configuration, one uses factory methods to create NEW INSTANCES (existing one is not changed). This allows complete thread-safe use at any point in life cycle.
This latter approach is preferred for future development, so new factory types will probably follow same style.
http://stackoverflow.com/questions/18611565/how-do-i-correctly-reuse-jackson-objectmapper
http://fasterxml.github.io/jackson-databind/javadoc/2.1.0/com/fasterxml/jackson/databind/ObjectReader.html
Builder object that can be used for per-serialization configuration of deserialization parameters, such as root type to use or object to update (instead of constructing new instance).
Uses "fluent" (or, kind of, builder) pattern so that instances are immutable (and thus fully thread-safe with no external synchronization); new instances are constructed for different configurations. Instances are initially constructed by
ObjectMapper
and can be reused, shared, cached; both because of thread-safety and because instances are relatively light-weight.https://dzone.com/articles/how-serialize-javautildate
public class JsonDateSerializer extends JsonSerializer<Date>{
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy");
public void serialize(Date date, JsonGenerator gen, SerializerProvider provider)
throws IOException, JsonProcessingException {
String formattedDate = dateFormat.format(date);
gen.writeString(formattedDate);
}
}
http://wiki.fasterxml.com/JacksonPolymorphicDeserialization
1.1. Global default typing
First, you can globally declare that certain types always require additional type information:
// one of: objectMapper.enableDefaultTyping(); // default to using DefaultTyping.OBJECT_AND_NON_CONCRETE objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
what this means is that for all types specified (for no-args, "Object.class" and all non-final classes), certain amount of default type information (Java class name, more specifically), is included, using default inclusion mechanism (additional wrapper array in JSON). This global default can be overridden by per-class annotations (more on this in next section).
The only thing you can configure, then, is just which types (classes) are affected. Choices are:
- JAVA_LANG_OBJECT: only affects properties of type Object.class
- OBJECT_AND_NON_CONCRETE: affects Object.class and all non-concrete types (abstract classes, interfaces)
- NON_CONCRETE_AND+_ARRAYS: same as above, and all array types of the same (direct elements are non-concrete types or Object.class)
- NON_FINAL: affects all types that are not declared 'final', and array types of non-final element types.
This is often simplest initial way to enable enough type information to get things going.
More granular (and powerful) way to define what type information to add, and where, is to use @JsonTypeInfo annotation (and possibly couple of related ones). For example, we could have annotated Animal as follows:
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class") class Animal { }
(which, incidentally is equivalent to the default settings for typing).
What does that mean?
- All instances of annotated type and its subtypes use these settings (unless overridden by another annotation)
- "Type identifier" to use is fully-qualified Java class name (like "org.codehaus.jackson.sample.Animal")
- Type identifier is to be included as a (meta-)property, along with regular data properties; using name "@class" (default name to use depend on type if: for classes it would be "@class")
- Use default type resolver (no @JsonTypeResolver added); as well as default type id resolver (no @JsonTypeIdResolver)
ObjectMapper mapper = new ObjectMapper();
File from = new File("albumnList.txt");
TypeReference<HashMap<String,Object>> typeRef
= new TypeReference<HashMap<String,Object>>() {};
HashMap<String,Object> o = mapper.readValue(from, typeRef);
Map<String, String> result = new ObjectMapper().readValue(
data, TypeFactory.mapType(HashMap.class, String.class, String.class));
On newer versions, try this: objectMapper.getTypeFactory().constructMapType(HashMap.class, String.class, String.class));JavaType javaType = objectMapper.getTypeFactory().constructParameterizedType(Map.class, Key.class, Value.class);
Map<Key, Value> map=objectMapper.readValue(jsonStr, javaType);
http://www.theotherian.com/2014/02/jackson-mixins-and-modules-external-classes.htmlfixing recursive relationship issues with mixins
@JsonFilter("thing filter")
public class ThingMixin {
}
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Thing.class, ThingMixin.class);
FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("thing filter", SimpleBeanPropertyFilter.serializeAllExcept("user"));
mapper.setFilters(filterProvider);
fixing classes that don't conform to the bean spec with modules and customer serializers
public class WidgetNameSerializer extends JsonSerializer<WidgetName> {
@Override
public void serialize(WidgetName widgetName, JsonGenerator jgen, SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeString(widgetName.value());
}
}
3. Explicitly ignoring properties: @JsonIgnore, @JsonIgnoreProperties
5. Ignoring all properties with specified type: @JsonIgnoreType
In addition to defining rules on per-property basis, there are times when it makes sense to just prevent serialization of any auto-detected properties for given type(s). For example, many frameworks add specific accessors for types they generate, which return objects that should not be serialized.
SON Filters are a way to implement fully dynamic filtering. The way this is done is by defining logical filter a property uses, with @JsonFilter("id") annotation, but specifying actual filter (and its configuration) using ObjectWriter. Filters themselves are obtained via FilterProviders which can be fully custom, or based on simple implementations
2. Configuring mapping from id to filter instance
Of mechanisms, latter one may be easier to understand and use: one just has to implement 'FilterProvider', which has but one method to implement:
public abstract class FilterProvider { public abstract BeanPropertyFilter findFilter(Object filterId); }
given this, 'SimpleFilterProvider' is little more than a Map<String,BeanPropertyFilter>, except for adding couple of convenience factory methods that build 'SimpleBeanPropertyFilter' instances given property names, so you typically just instantiate one with calls like:
SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.filterOutAllExcept("a"));
which would out all properties except for one named "a". This filter is then configured with ObjectMapper like so:
FilterProvider fp = new SimpleFilterProvider().addFilter("onlyAFilter", filter); objectMapper.writer(fp).writeValueAsString(pojo);
which would, then, apply to any Java type configured to use filter with id "onlyAFilter".
3. Configuring discovery of filter id
From above example we know we need to indicate classes that are to use our "onlyAFilter". The default mechanism is to use:
@JsonFilter("onlyAFilter") public class FilteredPOJO { //... }
But this is just the default. How so? The way Jackson figures out its annotation-based configuration is actually indirect, and fully customizable: all interaction is through configured 'AnnotationIntrospector' object, which amongst other things defines this method:
public Object findFilterId(AnnotatedClass ac);
which is called when serializer needs to determine id of the filter to apply (if any) for given class. Since the default implementation (org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector) has everything else working fine, what we can do is to sub-class it and override this method.
For example:
For example:
public class MyFilteringIntrospector extends JacksonAnnotationIntrospector { @Override public Object findFilterId(AnnotatedClass ac) { // First, let's consider @JsonFilter by calling superclass Object id = super.findFilterId(ac); // but if not found, use our own heuristic; say, just use class name as filter id, if there's "Filter" in name: if (id == null) { String name = ac.getName(); if (name.indexOf("Filter") >= 0) { id = name; } } return id; } }http://www.cowtowncoder.com/blog/archives/2011/09/entry_461.html
https://github.com/PressAssociation/partial-response/tree/master/filter-json-jackson
https://jira.spring.io/browse/SPR-7156
http://javaactive.blogspot.com/2014/05/how-to-implement-jackson-filters-to.html
@JsonFilter(com.test.ProductModel)
public class ProductModel implements IModel {
private String id ;
private String name ;
....
....
...getter and setter methods...
}
Filtering mechanism
public static String filterJsonFields(IModel model,
String jsonFilter, String fieldsQueryParam) throws IOException {
String jsonResult = null ;
SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.
serializeAllExcept(Collections.<String> emptySet());
Set<String> filterProps = new HashSet<String>();
if (fieldsQueryParam != null) {
StringTokenizer st = new StringTokenizer(fieldsQueryParam, "," );
while (st.hasMoreTokens()) {
filterProps.add(st.nextToken());
}
filter = SimpleBeanPropertyFilter.filterOutAllExcept(filterProps);
}
ObjectMapper mapper = new ObjectMapper();
FilterProvider fProvider = new SimpleFilterProvider().addFilter(jsonFilter, filter)
// setFailOnUnknownId: Ignore filtering the reference member fields
// Refer: https://jira.codehaus.org/browse/JACKSON-650
.setFailOnUnknownId( false );
try {
jsonResult = mapper.writer(fProvider).writeValueAsString(model);
} catch (IOException e) {
throw e;
}
return jsonResult;
}
http://www.baeldung.com/jackson-serialize-field-custom-criteria
@JsonFilter
(
"myFilter"
)
PropertyFilter theFilter =
new
SimpleBeanPropertyFilter() {
@Override
public
void
serializeAsField
(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer)
throws
Exception {
if
(include(writer)) {
if
(!writer.getName().equals(
"intValue"
)) {
writer.serializeAsField(pojo, jgen, provider);
return
;
}
int
intValue = ((MyDtoWithFilter) pojo).getIntValue();
if
(intValue >=
0
) {
writer.serializeAsField(pojo, jgen, provider);
}
}
else
if
(!jgen.canOmitFields()) {
// since 2.3
writer.serializeAsOmittedField(pojo, jgen, provider);
}
}
@Override
protected
boolean
include(BeanPropertyWriter writer) {
return
true
;
}
@Override
protected
boolean
include(PropertyWriter writer) {
return
true
;
}
};
FilterProvider filters =
new
SimpleFilterProvider().addFilter(
"myFilter"
, theFilter);
MyDto dtoObject =
new
MyDto();
dtoObject.setIntValue(-
1
);
ObjectMapper mapper =
new
ObjectMapper();
String dtoAsString = mapper.writer(filters).writeValueAsString(dtoObject);
@JsonIgnoreProperties( { "country",
})
@JsonPropertyOrder(value={"title", "id", "version", "price", "summary"})
public interface AppDetailFilter {
}
@JsonFilter(mixin=AppDetailFilter.class)
http://stackoverflow.com/questions/28270621/using-jackson-to-de-serialize-a-scala-case-classUsing Jackson to (De)-serialize a Scala Case Class
Jackson is expecting your class to be a JavaBean, which means its expects the class to have a getX() and/or setX() for every property.
Option 1
You can create JavaBean classes in Scala using the annotation BeanProperty.
Example
case class Person(
@BeanProperty val name: String,
@BeanProperty val age: Int,
@BeanProperty val hobbies: Option[String]
)
In this case a val will mean only a getter is defined. If you want setters for deserialization you defined the properties as var.
Option 2
While option 1 will work, if you really want to use Jackson there are wrappers that allow it to deal with Scala classes like FasterXML's scala module which might be a better approach. I haven't used it as I've just been using the Json library built in to play.
Jackson supports read and write JSON via high-performance Jackson Streaming APIs, or incremental mode.
Jackson’s streaming processing is high-performance, fast and convenient, but it’s also difficult to use, because you need to handle each and every detail of JSON data.
JsonSerializer - SerializerProvider serializer
serializer.defaultSerializeValue(oct, jGen);
https://dzone.com/articles/latest-jackson-integration
Jackson2ObjectMapperBuilder
http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html
- Collection<Animal> animals =
- mapper.readValue(new File("input_2.json"),
- new TypeReference<Collection<Animal>>() {});
- System.out.println(mapper.writeValueAsString(animals));
- // or
- Collection<Animal> animals2 =
- mapper.readValue(new File("input_2.json"),
- TypeFactory.defaultInstance().constructParametricType(
- Collection.class, Animal.class));
USE_ANNOTATIONS(true),
How to ignore pojo annotations while using Jackson ObjectMapper?
http://stackoverflow.com/questions/31680046/how-to-ignore-pojo-annotations-while-using-jackson-objectmapper
ObjectMapper objectMapper = new ObjectMapper().configure(
org.codehaus.jackson.map.DeserializationConfig.Feature.USE_ANNOTATIONS, false) .configure(org.codehaus.jackson.map.SerializationConfig.Feature.USE_ANNOTATIONS, false);
http://www.baeldung.com/jackson-ignore-properties-on-serialization
@JsonProperty("anotherName")
@JsonIgnoreProperties(value = { "someField" })
@JsonIgnore
@JsonIgnoreType
public class SomeType { ... }
@JsonProperty
(
"strVal"
)
public
String getStringValue() {
This exception is thrown if Jackson can’t create instance of the class – this happens if the class is abstract or it is just an interface.
http://www.baeldung.com/jackson-serialize-datesJackson will serialize the Date to a timestamp format by default (number of milliseconds since January 1st, 1970, UTC).
ObjectMapper mapper =
new
ObjectMapper();
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
SimpleDateFormat df =
new
SimpleDateFormat(
"dd-MM-yyyy hh:mm"
);
ObjectMapper mapper =
new
ObjectMapper();
mapper.setDateFormat(df);
http://www.leveluplunch.com/java/tutorials/033-custom-jackson-date-deserializer/
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(Object.class, new CustomDateDeseralizer());
objectMapper.registerModule(simpleModule);
ObjectMapper
is thread safe. You only need one instance of it for for each configuration, i.e., if you need 2 different date formats, then you need 2 ObjectMapper
objects, or only one but you need to synchronize
the call to the setDateFormat
method.https://github.com/FasterXML/jackson-datatype-guava
ObjectMapper mapper = new ObjectMapper() .registerModule(new GuavaModule());http://stackoverflow.com/questions/25693309/using-jackson-objectmapper-with-java-8-optional-values
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Optional.class, OptionalMixin.class);
You could use jackson-datatype-jdk8 which is described as:
Support for new JDK8-specific types, such as Optional
To enable pretty print, use
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));writerWithDefaultPrettyPrinter
.http://www.baeldung.com/jackson-ignore-properties-on-serialization
@JsonIgnore
private
int
intValue;
@JsonFilter
(
"myFilter"
)
public
class
MyDtoWithFilter { ... }
SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter.serializeAllExcept(
"intValue"
);
FilterProvider filters =
new
SimpleFilterProvider().addFilter(
"myFilter"
, theFilter);
ObjectMapper mapper =
new
ObjectMapper();
SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter.serializeAllExcept(
"intValue"
);
FilterProvider filters =
new
SimpleFilterProvider().addFilter(
"myFilter"
, theFilter);
MyDtoWithFilter dtoObject =
new
MyDtoWithFilter();
4. Defining profiles for dynamic ignoral: JSON Views (@JsonView)
// Name is public @JsonView(Views.Public.class) String name; // Address semi-public @JsonView(Views.ExtendPublic.class) Address address; // SSN only for internal usage @JsonView(Views.Internal.class) SocialSecNumber ssn;
// or, starting with 1.5, more convenient (ObjectWriter is reusable too) objectMapper.viewWriter(ViewsPublic.class).writeValue(out, beanInstance);Views with JAX-RS
@JsonView(Views.Public.class) @GET @Produces(MediaType.APPLICATION_JSON ) public List<Object> getElements() {
By default all properties without explicit view definition are included in serialization.
http://stackoverflow.com/questions/16089651/jackson-serialization-ignore-empty-values-or-null
Jackson allows controlling this behavior at either the class level or field level.
@JsonInclude
(Include.NON_NULL)
@JsonInclude(Include.NON_NULL)
public static class Request {
...
}
The other option is to configure the
ObjectMapper
directly, simply by calling objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
http://stackoverflow.com/questions/39005703/jackson-annotations-difference-between-jsonignorepropertiesignoreunknown-true
@JsonInclude(Include.NON_EMPTY)
public static class Person {
[....]
}
Console output is:
http://stackoverflow.com/questions/21048020/jackson-jsonview-not-being-applied{"firstName":"Mark","lastName":"Watney"}
withView()
not mutating the existing config. However,objectMapper.setConfig(objectMapper.getSerializationConfig().withView(YourView.class));
works and is probably prefarable to subclassing ObjectMappe
Turns out if you actually read the docs you find out that you can't just change serialization configuration by calling getSerializationConfig and calling setters on it.
you can NOT change settings by accessing an instance and calling methods:
http://stackoverflow.com/questions/18043587/why-im-not-able-to-unwrapp-and-serialize-java-map-using-jackson-java-library
http://wiki.fasterxml.com/JacksonFeatureAnyGetter
@JsonUnwrapped
doesn't work for maps, only for proper POJOs with getters and setters. For maps, You should use @JsonAnyGetter
and @JsonAnySetter
(available in jackson version >= 1.6).http://code-willy.blogspot.com/2013/03/jersey-client-with-customize-json.htmlprivate void HashMap<String, String> properties; @JsonAnySetter public void add(String key, String value) { properties.put(key, value); } @JsonAnyGetter public Map<String,String> getProperties() { return properties; }
Jersey Client with Customize JSON (Jackson) Configuration
ClientConfig clientConfig = new DefaultClientConfig(); // Allow Jersey Client support JSON. clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE); // Create your own Jackson ObjectMapper. ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); // Create your own JacksonJaxbJsonProvider and then assign it to the config. JacksonJaxbJsonProvider jacksonProvider = new JacksonJaxbJsonProvider(); jacksonProvider.setMapper(mapper); clientConfig.getSingletons().add(jacksonProvider); Client client = Client.create(clientConfig);
@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)
Custom JSON Deserialization with Jacksonhttps://dzone.com/articles/custom-json-deserialization-with-jackson
public class ProgramDeserializer extends JsonDeserializer<Program> {
public Program deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ObjectCodec oc = jp.getCodec();
JsonNode node = oc.readTree(jp);
final Long id = node.get("id").asLong();
final String name = node.get("name").asText();
final String contents = node.get("contents").asText();
final long ownerId = node.get("ownerId").asLong();
User user = new User();
user.setId(ownerId);
return new Program(id, name, contents, user);
}
}
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Program.class, new ProgramDeserializer());
mapper.registerModule(module);
http://wiki.fasterxml.com/JacksonFeatureUnwrapping
@JsonUnwrapped public Location location;
which we would like to bind to (or from) JSON like:
{ "name" : "home", "latitude" : 127, "longitude" : 345 }
@JsonInclude(Include.NON_NULL)
Jackson supports annotation inheritance.
http://wiki.fasterxml.com/JacksonFAQDateHandlingobjectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
which disable use of timestamps (numbers), and instead use a [ISO-8601 ]-compliant notation, which gets output as something like: "1970-01-01T00:00:00.000+0000".
That format sucks, can I use my own?
If you must. You can configure formatting by passing a java.text.DateFormat instance like so:
objectMapper.setDateFormat(myDateFormat); // 1.8 and above objectMapper.getSerializationConfig().setDateFormat(myDateFormat); // for earlier versions (deprecated for 1.8+)
Can I configure it on per-property basis?
Yes, with Jackson 2.0 you can use the new @JsonFormat annotation:
public class DateStuff { @JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd,HH:00", timezone="CET") public Date creationTime; }
http://stackoverflow.com/questions/20563640/using-jackson-objectmapper-with-jersey
@Provider
public class JerseyMapperProvider implements ContextResolver<ObjectMapper> {
private static ObjectMapper apiMapper = ObjectMapperManager.createMapperForApi();
@Override
public ObjectMapper getContext(Class<?> type)
{
return apiMapper;
}
}
@JsonCreator
public static Test1 factory(double n) {
return new Test1(n);
}
http://wahdancsthoughts.blogspot.com/2013/06/json-polymorphic-types-with-jackson.html@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes({
@Type(value = Cat.class, name = "cat"),
@Type(value = Dog.class, name = "dog") })
http://www.mkyong.com/java/how-to-convert-java-map-to-from-json-jackson/
map = mapper.readValue(json, new TypeReference<Map<String, String>>(){});
json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(map);
JavaType collectionType = mapper.getTypeFactory().constructCollectionType(List.class, MyObject.class);List<MyObject> readValue = mapper.readValue(jsonString, collectionType);
http://www.baeldung.com/jackson-collection-array
MyDto[] asArray = mapper.readValue(jsonArray, MyDto[].
class
);
MyDto class needs to have the no-args default constructor – if it doesn’t, Jackson will not be able to instantiate it:
http://tutorials.jenkov.com/java-json/jackson-annotations.html
The
@JsonIgnoreType
Jackson annotation is used to mark a whole type (class) to be ignored everywhere that type is used. Here is an example that shows you how you could use the @JsonIgnoreType
annotation:@JsonSetter
The Jackson annotation
@JsonSetter
is used to tell Jackson that is should match the name of this setter method to a property name in the JSON data, when reading JSON into objects. This is useful if the property names used internally in your Java class is not the same as the property name used in the JSON file.@JsonSetter("id") public void setPersonId(long personId) { this.personId = personId; }
@JsonAnySetter
The Jackson annotation
@JsonAnySetter
instructs Jackson to call the same setter method for all unrecognized fields in the JSON object. By "unrecognized" I mean all fields that are not already mapped to a property or setter method in the Java objectpublic class Bag { private Map<String, Object> properties = new HashMap<>(); @JsonAnySetter public void set(String fieldName, Object value){ this.properties.put(fieldName, value); } public Object get(String fieldName){ return this.properties.get(fieldName); } }
@JsonCreator
The Jackson annotation
@JsonCreator
is used to tell Jackson that the Java object has a constructor (a "creator") which can match the fields of a JSON object to the fields of the Java object.
The
@JsonCreator
annotation is useful in situations where the @JsonSetter
annotation cannot be used. For instance, immutable objects do not have any setter methods, so they need their initial values injected into the constructor. Look at this PersonImmutable
class as example:@JsonCreator public PersonImmutable( @JsonProperty("id") long id, @JsonProperty("name") String name ) { this.id = id; this.name = name; }
@JsonGetter("id") public long personId() { return this.personId; } @JsonSetter("id") public void personId(long personId) { this.personId = personId; }
@JsonAnyGetter
The
@JsonAnyGetter
Jackson annotation enables you to use a Map
as container for properties that you want to serialize to JSON. Here is an example of using the @JsonAnyGetter
annotation in a Java class:public class PersonAnyGetter { private Map<String, Object> properties = new HashMap<>(); @JsonAnyGetter public Map<String, Object> properties() { return properties; } }
@JsonPropertyOrder({"name", "personId"})
Normally Jackson would have serialized the properties in
PersonPropertyOrder
in the sequence they are found in the class.@JsonRawValue
The
@JsonRawValue
Jackson annotation tells Jackson that this property value should written directly as it is to the JSON output. If the property is a String
Jackson would normally have enclosed the value in quotation marks, but if annotated with the @JsonRawValue
property Jackson won't do that.@JsonRawValue public String address = "{ \"street\" : \"Wall Street\", \"no\":1}";
CSV
https://github.com/FasterXML/jackson-dataformat-csv
// Schema from POJO (usually has @JsonPropertyOrder annotation) CsvSchema schema = mapper.schemaFor(Pojo.class); // Manually-built schema: one with type, others default to "STRING" CsvSchema schema = CsvSchema.builder() .addColumn("firstName") .addColumn("lastName") .addColumn("age", CsvSchema.ColumnType.NUMBER) .build(); // Read schema from the first line; start with bootstrap instance // to enable reading of schema from the first line // NOTE: reads schema and uses it for binding CsvSchema bootstrapSchema = CsvSchema.emptySchema().withHeader(); ObjectMapper mapper = new CsvMapper(); mapper.readerFor(Pojo.class).with(bootstrapSchema).readValue(json);
CSV content can be read either using
CsvFactory
(and parser, generators it creates) directly, or through CsvMapper
(extension of standard ObjectMapper
).
When using
CsvMapper
, you will be creating ObjectReader
or ObjectWriter
instances that pass CsvSchema
along toCsvParser
/ CsvGenerator
. When creating parser/generator directly, you will need to explicitly call setSchema(schema)
before starting to read/write content.
The most common method for reading CSV data, then, is:
CsvMapper mapper = new CsvMapper();
Pojo value = ...;
CsvSchema schema = mapper.schemaFor(Pojo.class); // schema from 'Pojo' definition
String csv = mapper.writer(schema).writeValueAsString(value);
Pojo result = mapper.readerFor(Pojo.class).with(schema).read(csv);
http://stackoverflow.com/questions/31685653/spring-boot-jersey-jackson/31703546#31703546
public ObjectMapperContextResolver() {
mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(
PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES
);
}
http://notes.stay4it.com/2016/02/29/http-related-mess-json-data-response/http://stackoverflow.com/questions/21787128/how-to-unit-test-jackson-jsonserializer-and-jsondeserializer
private ObjectMapper mapper;
private CustomerNumberDeserialiser deserializer;
@Before
public void setup() {
mapper = new ObjectMapper();
deserializer = new CustomerNumberDeserialiser();
}
@Test
public void floating_point_string_deserialises_to_Double_value() {
String json = String.format("{\"value\":%s}", "\"1.1\"");
Number deserialisedNumber = deserialiseNumber(json);
assertThat(deserialisedNumber, instanceOf(Double.class));
assertThat(deserialisedNumber, is(equalTo(1.1d)));
}
@SneakyThrows({JsonParseException.class, IOException.class})
private Number deserialiseNumber(String json) {
InputStream stream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
JsonParser parser = mapper.getFactory().createParser(stream);
DeserializationContext ctxt = mapper.getDeserializationContext();
parser.nextToken();
parser.nextToken();
parser.nextToken();
return deserializer.deserialize(parser, ctxt);
}