Simple Jackson w/
DropWizard (& beyond)
Tatu Saloranta
@cowtowncoder
tatu@fasterxml.com
● Assumes some familiarity with JAX-RS/DropWizard
● Jackson is the default DropWizard JSON provider
o … also on: RESTEasy, SpringMVC, Restlet, CXF
● Presentation mostly about data-binding
o reading JSON into Java Objects (POJOs)
o writing Java objects as JSON
● But Jackson offers more: Tree Model (JsonNode),
streaming read/write -- mix’n match!
● Not limited to JSON either (XML, CSV, ...)
Introduction
1. Often “just works”, esp. with bit of practice
2. or with minor adjustments to
a. POJO structure/naming, and/or
b. JSON structure/naming
3. or by using annotations (regular, mix-in)
4. perhaps with changed Jackson defaults
5. using a datatype module (guava, joda)
6. or, using a more dynamic Java representation
a. Tree Model (JsonNode) or “untyped” (Maps of Lists)
7. Rarely if ever need custom handlers! (last resort)
Simple Usage: Claims
● W/ default settings, Jackson reads JSON
a. No-argument constructor (any visibility)
b. Setter (“setValue(x)”) with any visibility (even
private), OR
c. public field of same name (“value”)
● W/ default settings, Jackson writes JSON
a. Public getter (“getValue()”), OR
b. public field of same name (“value”)
Simple Usage: Just Works
// traditional Bean
public class Point {
private int x, y;
public Point() { }
public int getX() {
return x;
}
public void setX(int x){
this.x = x;
}
// and same for ‘y’
}
Simple Usage: Just Works, 2
// or just:
public class Point {
public int x, y;
}
=>{ “x”:100, “y”:200 }
● recursively (nested POJOs)
● for all common JDK types
o Maps, Collections, arrays
o Date/Calendar
o binary (byte[]) as base64
● Visibility rules, naming convention
configurable (default, per-class)
● Result of introspection, annotations is a
logical “Bean” type definition, with
a. “Creator” to use (default ctor, or creator)
b. Type, possibly polymorphic
c. Set of properties w/ accessors (getter/setter/field)
d. Filtering, type id/object id handler etc etc
Simple Usage: Just Works, 3
Sometimes default mapping not compatible:
● Naming not following bean style (C-style etc), or
individual properties “misnamed”
● Inadequate visibility (protected getters)
● No default constructor (can just add private one)
● Not all properties should be written in JSON
● All of above changeable via annotations too; but
sometimes simpler to just change class itself
Simple usage: Changing POJOs
● While ‘ON’ stands for ‘Object Notation’:
o JSON structures that do NOT map nicely;
especially union types (“String or Array”)
o does NOT support basic Object properties:
 Type metadata (no classes)
 Object identity
o multiple ways to express types, object identity:
choice has big effect (Jackson supports many)
● Mapping means fitting _both_ sides
Simple usage: Changing JSON
● @JsonProperty
o indicate inclusion, optionally different name
● @JsonIgnore
o indicate exclusion; either whole property, or just
accessor (if also @JsonProperty)
● @JsonPropertyOrder
o order of JSON properties has no semantics; but
sometimes nice to define output ordering
Simple usage: Annotations
● @JsonCreator (for arg-taking constructor)
o delegating (“first bind as X, give to my
constructor”) or property-based
● @JsonValue for scalar types (most often)
Simple usage: Annotations
public class MyTimeType {
@JsonValue
public String asString() { … }
}
@JsonIgnoreProperties(ignoreUnknown=true)
public class POJO
{
@JsonProperty(“name”)
private final String strName;
@JsonCreator // property-based (named properties)
protected POJO(@JsonProperty(“name”) String name) {
this.name = name;
}
@JsonIgnore
public String getInternalState() { … }
}
Simple usage: Annotation example
● Simple idea: associate, don’t embed!
o no need to modify target class, or bytecode
● Define an interface, (abstract) class with annotations
● Associate source class with target:
o mapper.addMixInAnnotations(target, source);
● Same as if ‘target’ had annotations that ‘source’ has,
from Jackson perspective
See http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html
for more detailed description.
Simple usage: mix-in annotations
● Visibility for introspection (hide/expose)
o mapper.setVisibility() (per accessor type)
o annotation: @JsonAutoDetect
o convenience vs. security
● Naming convention
o mapper.setPropertyNamingStrategy(x)
o annotation: @JsonNaming
o 3 standard implementations
(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_W
Simple usage: Jackson defaults
● For reading JSON, DeserializationFeature
o ACCEPT_SINGLE_VALUE_AS_ARRAY
o FAIL_ON_UNKNOWN_PROPERTIES
o USE_BIG_DECIMAL_FOR_FLOATS
● For writing JSON, SerializationFeature
o FAIL_ON_EMPTY_BEANS
o INDENT_OUTPUT
o WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED
● mapper.enable(...) / disable(...)
Simple usage: Jackson defaults
But someone may already have solved your
problem!
Datatype modules exist for these and more:
● Guava
● Hibernate
● High-Performance Primitive Collection (HPPC)
● Joda
See: https://github.com/FasterXML/jackson
Simple usage: datatype modules
● If structure (too)
dynamic, difficult to
match with POJO, or
o you just want a tiny
sliver, or you
o like JSON Pointer
● JsonNode similar to
XML DOM, ObjectNode
of json.org
Simple usage: go loose with Trees
JsonNode n = mapper.readTree(src);
String firstName = n
.path(“name”)
.path(“first”).asText();
// or with JSON Pointer:
String fn = n.at(“/name/first”)
.asText();
for (JsonNode child:
n.path(“children”)) {
int age = child.path(“age”).asInt
}
● Not either or choice: can go back & forth:
Person person = mapper.treeToValue(root,
Person.class);
JsonNode childNode = mapper.valueToTree(
person.getChildren().get(0));
● Jackson can read/write JsonNodes just like POJOs;
even have JsonNode-valued properties.
Simple usage: Trees, 2
That’s All, Folks! Questions?
Visit Jackson home at
https://github.com/FasterXML/jackson
and/or join mailing lists at
https://groups.google.com/forum/#!forum/jack
son-user
Simple usage: in closing

Simple Jackson with DropWizard

  • 1.
    Simple Jackson w/ DropWizard(& beyond) Tatu Saloranta @cowtowncoder tatu@fasterxml.com
  • 2.
    ● Assumes somefamiliarity with JAX-RS/DropWizard ● Jackson is the default DropWizard JSON provider o … also on: RESTEasy, SpringMVC, Restlet, CXF ● Presentation mostly about data-binding o reading JSON into Java Objects (POJOs) o writing Java objects as JSON ● But Jackson offers more: Tree Model (JsonNode), streaming read/write -- mix’n match! ● Not limited to JSON either (XML, CSV, ...) Introduction
  • 3.
    1. Often “justworks”, esp. with bit of practice 2. or with minor adjustments to a. POJO structure/naming, and/or b. JSON structure/naming 3. or by using annotations (regular, mix-in) 4. perhaps with changed Jackson defaults 5. using a datatype module (guava, joda) 6. or, using a more dynamic Java representation a. Tree Model (JsonNode) or “untyped” (Maps of Lists) 7. Rarely if ever need custom handlers! (last resort) Simple Usage: Claims
  • 4.
    ● W/ defaultsettings, Jackson reads JSON a. No-argument constructor (any visibility) b. Setter (“setValue(x)”) with any visibility (even private), OR c. public field of same name (“value”) ● W/ default settings, Jackson writes JSON a. Public getter (“getValue()”), OR b. public field of same name (“value”) Simple Usage: Just Works
  • 5.
    // traditional Bean publicclass Point { private int x, y; public Point() { } public int getX() { return x; } public void setX(int x){ this.x = x; } // and same for ‘y’ } Simple Usage: Just Works, 2 // or just: public class Point { public int x, y; } =>{ “x”:100, “y”:200 } ● recursively (nested POJOs) ● for all common JDK types o Maps, Collections, arrays o Date/Calendar o binary (byte[]) as base64
  • 6.
    ● Visibility rules,naming convention configurable (default, per-class) ● Result of introspection, annotations is a logical “Bean” type definition, with a. “Creator” to use (default ctor, or creator) b. Type, possibly polymorphic c. Set of properties w/ accessors (getter/setter/field) d. Filtering, type id/object id handler etc etc Simple Usage: Just Works, 3
  • 7.
    Sometimes default mappingnot compatible: ● Naming not following bean style (C-style etc), or individual properties “misnamed” ● Inadequate visibility (protected getters) ● No default constructor (can just add private one) ● Not all properties should be written in JSON ● All of above changeable via annotations too; but sometimes simpler to just change class itself Simple usage: Changing POJOs
  • 8.
    ● While ‘ON’stands for ‘Object Notation’: o JSON structures that do NOT map nicely; especially union types (“String or Array”) o does NOT support basic Object properties:  Type metadata (no classes)  Object identity o multiple ways to express types, object identity: choice has big effect (Jackson supports many) ● Mapping means fitting _both_ sides Simple usage: Changing JSON
  • 9.
    ● @JsonProperty o indicateinclusion, optionally different name ● @JsonIgnore o indicate exclusion; either whole property, or just accessor (if also @JsonProperty) ● @JsonPropertyOrder o order of JSON properties has no semantics; but sometimes nice to define output ordering Simple usage: Annotations
  • 10.
    ● @JsonCreator (forarg-taking constructor) o delegating (“first bind as X, give to my constructor”) or property-based ● @JsonValue for scalar types (most often) Simple usage: Annotations public class MyTimeType { @JsonValue public String asString() { … } }
  • 11.
    @JsonIgnoreProperties(ignoreUnknown=true) public class POJO { @JsonProperty(“name”) privatefinal String strName; @JsonCreator // property-based (named properties) protected POJO(@JsonProperty(“name”) String name) { this.name = name; } @JsonIgnore public String getInternalState() { … } } Simple usage: Annotation example
  • 12.
    ● Simple idea:associate, don’t embed! o no need to modify target class, or bytecode ● Define an interface, (abstract) class with annotations ● Associate source class with target: o mapper.addMixInAnnotations(target, source); ● Same as if ‘target’ had annotations that ‘source’ has, from Jackson perspective See http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html for more detailed description. Simple usage: mix-in annotations
  • 13.
    ● Visibility forintrospection (hide/expose) o mapper.setVisibility() (per accessor type) o annotation: @JsonAutoDetect o convenience vs. security ● Naming convention o mapper.setPropertyNamingStrategy(x) o annotation: @JsonNaming o 3 standard implementations (PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_W Simple usage: Jackson defaults
  • 14.
    ● For readingJSON, DeserializationFeature o ACCEPT_SINGLE_VALUE_AS_ARRAY o FAIL_ON_UNKNOWN_PROPERTIES o USE_BIG_DECIMAL_FOR_FLOATS ● For writing JSON, SerializationFeature o FAIL_ON_EMPTY_BEANS o INDENT_OUTPUT o WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED ● mapper.enable(...) / disable(...) Simple usage: Jackson defaults
  • 15.
    But someone mayalready have solved your problem! Datatype modules exist for these and more: ● Guava ● Hibernate ● High-Performance Primitive Collection (HPPC) ● Joda See: https://github.com/FasterXML/jackson Simple usage: datatype modules
  • 16.
    ● If structure(too) dynamic, difficult to match with POJO, or o you just want a tiny sliver, or you o like JSON Pointer ● JsonNode similar to XML DOM, ObjectNode of json.org Simple usage: go loose with Trees JsonNode n = mapper.readTree(src); String firstName = n .path(“name”) .path(“first”).asText(); // or with JSON Pointer: String fn = n.at(“/name/first”) .asText(); for (JsonNode child: n.path(“children”)) { int age = child.path(“age”).asInt }
  • 17.
    ● Not eitheror choice: can go back & forth: Person person = mapper.treeToValue(root, Person.class); JsonNode childNode = mapper.valueToTree( person.getChildren().get(0)); ● Jackson can read/write JsonNodes just like POJOs; even have JsonNode-valued properties. Simple usage: Trees, 2
  • 18.
    That’s All, Folks!Questions? Visit Jackson home at https://github.com/FasterXML/jackson and/or join mailing lists at https://groups.google.com/forum/#!forum/jack son-user Simple usage: in closing