Contents


Get started with the JSON Binding API, Part 3

Custom binding with JSON-B

Customize JSON binding with annotations and runtime configuration

Comments

Content series:

This content is part # of 4 in the series: Get started with the JSON Binding API, Part 3

Stay tuned for additional content in this series.

This content is part of the series:Get started with the JSON Binding API, Part 3

Stay tuned for additional content in this series.

The first article in this series presented an overview of JSON-B, including a first look at using annotations and runtime configuration to customize binding behavior. This article is a more in-depth, hands-on introduction to these two mechanisms. You'll learn how to use annotations and runtime configuration separately or combine them, and how to understand the interplay between them in custom solutions. You'll also get a first look at JSON-B adapters and low-level serializers and deserializers, which you can use to customize the logic of operations in JSON-B.

Two ways to customize JSON-B (recap)

Annotations and runtime configuration can be used together or separately to customize JSON binding in your Java™ enterprise applications. If you’ve read Part 1, the following code samples should refresh your memory about how the models work.

Compile-time annotations

JSON-B offers a number of built-in annotations, which you can use to mark the field, class, parameter, or setter/getter where you wish to enable custom behavior. Listing 1 is an example.

Listing 1. Example of using the annotation model
public class Book {
  @JsonbProperty("isbn")
  public String id;
}

Here, the name of the id field in the serialized JSON document will be renamed to isbn. To successfully deserialize to a Book instance, the JSON document must have a property named isbn.

Runtime configuration

If you prefer runtime configuration to annotations, you may build a configuration strategy and pass it to the Jsonb instance used to perform serialization and deserialization. This approach is shown in Listing 2.

Listing 2. Example of using the runtime model
JsonbConfig jsonbConfig = new JsonbConfig()
   .withPropertyNamingStrategy(
     PropertyNamingStrategy.LOWER_CASE_WITH_DASHES);

String json = JsonbBuilder.create(jsonbConfig).toJson(book);

In Listing 2, you can see that the property naming strategy is set on the JsonbConfig instance, and then passed to the factory method that creates the JsonBuilder instance. When the created Jsonb instance is used to serialize or deserialize, the property naming strategy is used. In this case the property names are converted to lowercase and delimited by dashes.

Customizing property names

The name of a property is determined by the name of the corresponding Java bean’s field name. On serialization, the field name is used as the property name in the output JSON document. On deserialization, the property name is matched to the field name and the appropriate setter is called, or a public field is set.

In some cases, the default naming strategy is not well suited for the problem you are trying to solve. It might be that the JSON document has a different naming convention from the one used by your business entity, or perhaps you are required to export your data to a JSON document format that does not match your business object’s structure.

Whatever the scenario, customizing the property name is one way to create greater flexibility upon serialization and deserialization. One way to do this is to use the @JsonbProperty annotation on a field, parameter, getter, or setter. In this case, the customized name is passed to the annotation as a value. Some rules to know:

  • If the annotation is placed on a field then the customized name is used for both serialization and deserialization.
  • If the annotation is placed on a setter method, then the customized name is only used for deserialization.
  • If the annotation is placed on a getter method, then it is only used for serialization.

Listing 3 shows property names being customized for the id, title, and author fields of the Book class introduced in the last article.

Listing 3. The Book class annotated with @JsonbProperty
public class Book {

  @JsonbProperty("isbn")
  private String id;
  private String title;
  private String author;

  @JsonbProperty("bookTitle")
  public String getTitle() {
      return title;
  }

  @JsonbProperty("authorName")
  public void setAuthor(String author) {
      this.author = author;
  }

  // other getters and setters omitted for brevity
}

The serialization of a Book instance results in a JSON document like the one in Listing 4.

Listing 4. Serialized Book instance in a JSON document
{
 "author": "Alex Theedom",
 "bookTitle": "Fun with JSON-B",
 "isbn": "ABC-123-XYZ"
}

Notice that in Listing 4, the author field retains its name unchanged. This is because only the setter method of the Book class in Listing 3 is annotated. As a result, the @JsonbProperty and getter methods are only called during deserialization. In order to successfully deserialize the JSON document in Listing 4 back to a Book instance, you would have to manually edit the author field to authorName.

It is also possible to use different custom names for serialization and deserialization, or to use different custom names on fields, getters, and setters in the same POJO. In this case, it is important to know that the customization on the getter and setter will take precedence over the customization on the field.

Customizing the property naming strategy

How a field name is translated to a property is determined by the property naming strategy. By default, the name is translated unchanged, but you can customize it. For instance you might choose to have the property name delimited by underscores or transformed to lowercase. Table 1 (below) shows the complete list of property naming strategies.

You configure the property naming strategy with the runtime model, by setting the appropriate value on a JsonbConfig instance. This is shown in Listing 5.

Listing 5. Configure the property naming strategy
public class Magazine {
  private String title;
  private Author authorName;
  private String internalAuditCode;
  private String alternativetitle;
  // getters and setters omitted for brevity
}

Magazine magazine = 
  new Magazine("Fun with JSON binding",
               new Author("Alex", "Theedom"),
               "ABC-123","Fun with JSON-B
               ");

JsonbConfig jsonbConfig = new JsonbConfig()
      .withPropertyNamingStrategy(
           PropertyNamingStrategy.LOWER_CASE_WITH_DASHES);

String json = JsonbBuilder.create(jsonbConfig).toJson(magazine);

The strategy in Listing 5 translates all field names to lowercase with dashes delimiting case differences. Listing 6 shows the output.

Listing 6. The LOWER_CASE_WITH_DASHES serialization strategy
{
  "alternativetitle": "Fun with JSON-B",
  "author-name": {
    "first-name": "Alex",
    "last-name": "Theedom"
  },
  "title": "Fun with JSON binding"
}

There are six property naming strategies to choose from, summarized in Table 1.

Table 1. Property name strategies
StrategyDescriptionOriginalTranslated Property Name
IDENTITYThe name is unchanged (default strategy).authorNameauthorName
LOWER_CASE_WITH_DASHESThe name is translated to lowercase with dashes delimiting differences in case.authorName
alternativetitle
author-name
alternativetitle
LOWER_CASE_WITH_UNDERSCORESThe name is translated to lowercase with underscores delimiting differences in case.authorName
alternativetitle
author_name
alternativetitle
UPPER_CAMEL_CASEThe first character is capitalized.authorName
alternativetitle
AuthorName
Alternativetitle
UPPER_CAMEL_CASE_WITH_SPACESThe first character is capitalized with spaces delimiting differences in case.authorName
alternativetitle
Author Name
Alternativetitle
CASE_INSENSITIVEThe Identity strategy is used for serialization, but for deserialization the property name is insensitive to case.AuthorNAME
maps to
authorName

Note, again, that fields configured with the @JsonbProperty annotation take precedence over the runtime-configured naming strategy specified on JsonbConfig.

Customizing the property-order strategy

The order in which properties appear in a JSON document is lexicographical by default. That and two additional property-order strategies are shown in Table 2.

Table 2. Default and custom property-order strategies
StrategyDescription
LEXICOGRAPHICALProperties are ordered lexicographically (default strategy).
ANYThere is no guaranteed order to properties.
REVERSEProperties are ordered reverse-lexicographically.

If you wanted to use the runtime model to configure the property-order strategy, you would do so by setting the appropriate strategy on a JsonbConfig instance. In Listing 7, we set the property-order strategy to reverse-lexicographical order.

Listing 7. Serializing with the REVERSE property-order strategy
Magazine magazine = 
    new Magazine("Fun with JSON binding", 
        new Author("Alex", "Theedom"), 
        "Fun with JSON-B");

JsonbConfig jsonbConfig = new JsonbConfig()
      .withPropertyOrderStrategy(PropertyOrderStrategy.REVERSE);

String json = JsonbBuilder.create(jsonbConfig).toJson(magazine);

Listing 8 shows the JSON output for this strategy.

Listing 8. Output of the REVERSE property-order strategy
{
 "title": "Fun with JSON binding",
 "authorName": {
   "lastName": "Theedom",
   "firstName": "Alex"
 },
 "alternativeTitle": "Fun with JSON-B"
}

Another option is to use the @JsonbPropertyOrder annotation to explicitly specify the desired property order. In this case you would pass the list of property names to the @JsonbPropertyOrder annotation, as shown in Listing 9. Properties not specified on the list are listed in lexicographical order after the ordered properties.

Listing 9. Output of Book instance using @JsonbPropertyOrder
@JsonbPropertyOrder(value = {"id", "title", "author"})
public class Book {
  private String id;
  private String title;
  private String author;
  // getters and setters omitted for brevity
}

In Listing 9, you see the custom ordering logic applied to the named properties from Listing 3. The order specified by @JsonbPropertyOrder overrides the default property-order strategy, as well as any runtime configurations. The new strategy applies to property names that have already been renamed.

Customizing field visibility

JSON Binding hands developers sophisticated control over the visibility and inclusion of fields during the serialization and deserialization process.

As an example, fields annotated @JsonbTransient are not included in the JSON document and are ignored during deserialization. Only the field and getter/setter methods can be annotated this way. It is not valid or logical to annotate at the class level.

Alternatively, you may configure the visibility characteristics of a class’s fields. By default, only public fields and getter/setter methods are used for serialization and deserialization, but you may customize access to be more or less restrictive.

Field visibility strategy is defined in a custom implementation of the PropertyVisibilityStrategy interface, where two overloaded methods—isVisible(Field) and isVisibile(Method)—control access to the respective field or method values. Listing 10 shows an example implementation.

Listing 10. An example implementation of PropertyVisibilityStrategy
PropertyVisibilityStrategy vis = new PropertyVisibilityStrategy() {
  @Override
  public boolean isVisible(Field field) {
      return Modifier.isProtected(field.getModifiers());
  }

  @Override
  public boolean isVisible(Method method) {
      return !method.getName().contains("AlternativeTitle");
  }
};

An instance of the PropertyVisibilityStrategy type is set on the JsonbConfig instance, as shown in Listing 11.

Listing 11. Configuring serialization to use the PropertyVisibilityStrategy
Magazine magazine = 
    new Magazine("Fun with JSON binding", 
    new Author("Alex", "Theedom"), 
    "Fun with JSON-B");

JsonbConfig jsonbConfig = new JsonbConfig()
      .withPropertyVisibilityStrategy(vis);

String json = JsonbBuilder.create(jsonbConfig).toJson(magazine);

The isVisible() method

During the serialization process the object is traversed using reflection and each getter method object is passed to the isVisible() method. Within this method you can write logic to determine if the method should be called. If so, true is returned to indicate that the method’s return value should be included in the JSON document output. In Listing 10, the isVisible() method returns false when the getAlternativeTitle() method is passed, and therefore the related field will not be included in the JSON output. True is returned for all other methods and thus their property values will be included.

The isVisible() method that accepts a field will not be called in the above example, because the serialization operation is configured to call JavaBean methods. If no bean methods existed, the serializer and deserializer would attempt to access the instance’s public fields.

In this case, I have overridden the isVisible() method with code that enables only fields with the protected modifier. In a scenario where the Java instance does not have any bean methods, only fields with the protected modifier would be accessed and included in the outputted JSON document.

Customizing null handling

On serialization, object fields with null values are ignored and null values in collections are preserved by default. During deserialization, nulls in JSON properties set the corresponding object field to null. If the target field is an Optional, the value will be set to Optional.empty(). There are three ways to customize this default behavior.

Using @JsonbNillable

Your first option is to annotate the package or class with @JsonbNillable. The customization applies to all fields in the entire package or class, and all nulls will be preserved during serialization and deserialization. In Listing 12, the title field is annotated @JsonbNillable.

Listing 12. The Book class with title field annotated @JsonbNillable
public class Book {
  private String id;
  @JsonbNillable
  private String title;
  private String author;
  // getters and setters omitted for brevity
}

Using the nillable flag

Another way to achieve the same solution is to annotate the relevant field or JavaBean property with @JsonbProperty, and to set its nillable flag to true, as shown in Listing 13.

Listing 13. The Magazine class with authorName field annotated @JsonbProperty
public class Magazine {
  private String title;
  @JsonbProperty(nillable = true)
  private Author authorName;
  private String alternativeTitle;
  // getters and setters omitted for brevity
}

When conflicting configurations occur, precedence is given to the annotation with the smallest scope. Thus, the @JsonbProperty annotation with nillable = false overrides the @JsonbNillable annotation applied to the class.

Using withNullValues()

The final way to customize null handling is to pass true or false to the withNullValues() method on a JsonbConfig instance. Listing 14 shows the configuration of a JsonbConfig instance with null values set to true.

Listing 14. Configuring a JsonbConfig instance with null values set to true
JsonbConfig jsonbConfig = new JsonbConfig().withNullValues(true);
Booklet booklet = new Booklet("Fun with Java EE", null, null);
String json = JsonbBuilder.create(jsonbConfig).toJson(booklet);

The output JSON document of the Booklet instance is shown in Listing 15.

Listing 15. The JSON document showing preserved null values
{
 "author": {
   "firstName": null,
   "lastName": null
 },
 "title": "Fun with Java EE"
}

Customizing object creation

JSON-B expects all classes to have a public no-argument constructor, which it uses during deserialization to instantiate the target class. Once the instance is created, it is populated with data from the JSON document by calling the appropriate setter method or by directly setting the public field.

This approach works for most simple scenarios, but may be insufficient for more complex constructions. For these cases, you will need to implement a custom constructor or static factory method. Listing 16 shows such a custom constructor.

Listing 16. Custom constructor
public class Magazine {
  private String title;
  private Author authorName;

  @JsonbCreator
  public Magazine(@JsonbProperty("bookTitle") String title,
                  @JsonbProperty("firstName") String firstName,
                  @JsonbProperty("surname") String lastName) {
      this.title = title;
      this.authorName = new Author(firstName, lastName);
  }
  // getters and setters omitted for brevity
}

Notice the use of the @JsonbProperty annotation to map JSON property names to parameters in the constructor’s parameter list. The JSON document in Listing 17 is successfully deserialized to the Magazine class in Listing 16.

Listing 17. Magazine JSON document
{
 "firstName": "Alex",
 "surname": "Theedom",
 "bookTitle": "Fun with JSON-B"
}

I’ll also demonstrate a more sophisticated customization of the serialization and deserialization process in the section covering JSON-B adapters.

Customizing date and time formats

Dealing with dates and times can be a headache, no matter what. Fortunately, the new JSON Binding API offers a packet of features making it easier to customize these formats.

You can use the annotation @JsonbDateFormat to configure date and time formats at every level, from the package to the field. In Listing 18, we annotate just the setter method, so that the date format will be applied only during deserialization. If we annotated just the getter method, the date format would be applied only during serialization.

Listing 18. Date format customized for deserialization only
public class Magazine {
  private String title;
  private Author authorName;
  private LocalDate localDate;

  @JsonbDateFormat(value = "MM/dd/yyyy", locale = "Locale.ENGLISH")
  public void setLocalDate(LocalDate localDate) {
      this.localDate = localDate;
  }
  // other getter and setters omitted for brevity
}

You can also use the runtime model to customize the date format, as shown in Listing 19. In this case, the date format and locale are set on the JsonbConfig instance using the withDateFormat() method.

Listing 19. Set the date format on the JsonbConfig instance
String json = "{\"published\":\"10/10/2018\",
                \"author\":\"Alex Theedom\",
                \"title\":\"Fun with JSON-B\"}";

JsonbConfig jsonbConfig = new JsonbConfig()
    .withDateFormat("MM/dd/yyyy", Locale.ENGLISH);

JsonbBuilder.create(jsonbConfig).fromJson(json, Book.class);

Customizing number formats

Number properties can be explicitly formatted by passing a string of special number-pattern characters to the @JsonbNumberFormat annotation. Listing 20 shows how you would format a number with the pattern "#.00".

Listing 20. Define a number format for a numeric field
public class Booklet {
  private String title;
  private Author author;

  @JsonbNumberFormat("#.00")
  private double price;
}

The @JsonbNumberFormat annotation can mark the package, class, getter/setter, parameter, or field.

See the Javadoc for the java.text.DecimalFormat class for a detailed discussion of number-pattern formats.

Global runtime customizations

Many of the customizations discussed so far can be specified to work locally on a field or method or globally on all operations performed. In the following section you will see the remaining runtime configurations that have only a global element.

Customizing binary data handling

The three binary data handling strategies are BYTE, BYTE_64, and BYTE_64_URL. To customize the binary data handling strategy, simply pass the method withBinaryDataStrategy() one of these three static constants, as shown in Listing 21.

Listing 21. Binary strategy
new JsonbConfig()
  .withBinaryDataStrategy(BinaryDataStrategy.BASE_64_URL);

Configuring I-JSON

I-JSON is a restricted profile of JSON designed to maximize interoperability. By default JSON-B conforms loosely with this profile. In cases where you need to ensure strict compliance, you may enable it by setting the StrictISON flag to true on an instance of JsonbConfig. Listing 22 shows how to configure this.

Listing 22. Setting strict I-JSON
new JsonbConfig().withStrictIJSON(true);

Customizing character encoding

The binding operations will use the encoding type specified by this property for encoding JSON data. Listing 23 shows an example.

Listing 23. Set the default encoding
JsonbConfig jsonbConfig = new JsonbConfig().withEncoding("UTF-32");

Valid character encoding are defined in RFC 7159 Section 8.

Customizing a default locale

The locale can be set as shown in Listing 24.

Listing 24. Set the default Locale
JsonbConfig jsonbConfig = new JsonbConfig()
  .withLocale(Locale.CANADA);

Customizing prettified JSON output

You can set the output of the serialization process to use prettified JSON with appropriate linefeeds and indentations. Listing 25 shows the configuration for this.

Listing 25. Output prettified JSON
JsonbConfig jsonbConfig = new JsonbConfig().withFormatting(true);

Customizing serialization and deserialization

You can only go so far with the simple annotations and configuration flags introduced so far. At some point, you will require a more robust and adaptable solution. JSON-B’s adapters and low-level serialization and deserialization features were introduced for just these scenarios.

JSON-B adapters

An adapter configures custom object creation and serialization by implementing methods from the JsonBAdapter interface. You may use JSON-B adapters to overwrite the methods adaptToJson() and adaptFromJson() with new logic for serialization and deserialization.

Listing 26 is an implementation of the adaptToJson() method with code that transforms the Booklet object into a JsonObject. Using the JSON Object Builder from the JSON Processing API, the adaptFromJson() method constructs a Booklet object from a JsonObject instance.

Listing 26. Implementation of the JsonbAdapter interface
public class BookletAdapter implements JsonbAdapter<Booklet, JsonObject> {

  @Override
  public JsonObject adaptToJson(Booklet booklet) {
      return Json.createObjectBuilder()
              .add("title", booklet.getTitle())
              .add("firstName", booklet.getAuthor().getFirstName())
              .add("lastName", booklet.getAuthor().getLastName())
              .build();
  }

  @Override
  public Booklet adaptFromJson(JsonObject json) {
      Booklet booklet = new Booklet(
              json.getString("title"),
              new Author(json.getString("firstName"),
   json.getString("lastName")));
      return booklet;
  }
}

As you can see from Listing 28, the adaptToJson() method "flattens" the Author object to two properties: firstName and lastName. As show in Listing 27, when given an instance of the Booklet class, adaptFromJson() reconstructs the Author object and outputs a Booklet instance.

Listing 27. The Booklet and Author class
public class Booklet {
  	private String title;
  	private Author author;
    // getters and setters omitted for brevity
}

public class Author {
  private String firstName;
  private String lastName;
  // getters and setters omitted for brevity
}

Listing 28 shows the output Booklet instance.

Listing 28. A serialized Booklet object
{
 "title": "Fun with JSON-B",
 "firstName": "Alex",
 "lastName": "Theedom"
}

Using a field-level JsonbAdapter

The JsonbAdapter is very flexible and can be used to customize the serialization and deserialization of individual fields as well as entire objects. This is achieved by marking the field, method, or class that should receive customized behavior with the annotation @JsonbTypeAdapter, and by passing it the class name of the JsonbAdapter to use.

In Listing 29, the firstName field is marked with the @JsonbTypeAdapter and the FirstNameAdapter class specified as the adapter.

Listing 29. Specify the FirstNameAdapter> for the firstName field
public class Author {
  private String lastName;
  @JsonbTypeAdapter(FirstNameAdapter.class)
  private String firstName;
  // getters and setters omitted for brevity
}

Listing 30 shows the implementation of the FirstNameAdapter class.

Listing 30. The FirstNameAdapter adapter
public class FirstNameAdapter 
implements JsonbAdapter<String, JsonValue> {

  @Override
  public JsonValue adaptToJson(String firstName) {
      return Json.createValue(firstName.subSequence(0,1).toString());
  }

  @Override
  public String adaptFromJson(JsonValue json) {
      return json.toString();
  }
}

The adapter type is determined depending on whether it should adapt an object or a field. If adapting an object, then the JsonObject type is used; if adapting a field, then the JsonValue type is used. If the field type is an array, then the JsonArray type is used.

Low-level serializer and deserializer customization

JSON-B serializers and deserializers are the lowest level of customization available and give access to the parsers and generators found in the JSON Processing API.

A custom serializer must implement the JsonbSerializer interface and provide logic for the serialize() method. Listing 31 shows an example of how to customize the serialization of the a book object.

Listing 31. Customized serialization of the Book class
public class BookSerializer implements JsonbSerializer<Book> {
  @Override
  public void serialize(Book book, JsonGenerator generator, SerializationContext ctx) {
      generator.writeStartObject();
      generator.write("id", "QWE-123-RTS");
      generator.write("title", book.getTitle());
      generator.write("firstName", book.getAuthor().split(" ")[0]);
      generator.write("lastName", book.getAuthor().split(" ")[1]);
      generator.writeEnd();
  }
}

In this example, the JsonGenerator is used to create a JSON document, property by property. The value of the id property is fixed and the author’s name is flattened to the firstName and lastName property.

The deserialization operation is customized by implementing the JsonbDeserializer interface and providing logic for the deserialize() method. The example in Listing 32 extracts just the Book's id from the JSON document.

Listing 32. Customized deserialization of the Book class
public class BookDeserializer implements JsonbDeserializer<String> {
  @Override
  public String deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) {
      while (parser.hasNext()) {
          JsonParser.Event event = parser.next();
          if (event == JsonParser.Event.KEY_NAME) {
              String keyName = parser.getString();
              if (keyName.equals("id")) {
                  return ctx.deserialize(String.class, parser);
              }
          }
          parser.next();
      }
      return "";
  }
}

Instances of the serializer and deserializer are registered with a JsonbConfig via the appropriate withDeserializers() or withSerializers(), as shown in Listing 33.

Listing 33. Register both serializers and deserializers
JsonbConfig config = new JsonbConfig()
      .withDeserializers(new BookDeserializer())
      .withSerializers(new BookSerializer());

Alternatively, you could annotate the type with @JsonbTypeSerializer or @JsonbTypeDeserializer and pass the class name of the relevant customization class.

Conclusion

JSON-B’s designers have set out to standardize the way developers transform Java objects to JSON documents and vice versa. If the API and features you’ve learned so far seem familiar to you, that is intentional: the API standardizes serialization and deserialization techniques that should be familiar to most Java developers.

The two customization models, runtime and compile-time, offer a highly flexible and intuitive way to finetune the API. The self-describing annotations and configuration methods contribute to productivity and ease in the development cycle. With these models, it is just as easy to manipulate lower-level serialization and deserialization operations as it is to perform advanced customizations.

JSON-B's ability to elegantly handle Java SE 8 features such as Optional and the new Date/Time API place it ahead of many other leading JSON parsers, which struggle to process these language constructs. You'll see this for yourself in the next and final part of this series, where I compare JSON-B to two other very popular JSON parsers: Jackson and GSON.

Test your understanding

  1. Which of the following mechanisms can be used to customize default behavior?
    1. Annotation package, class, field, and getter/setter methods
    2. XML configuration files
    3. Configure a JsonbConfig instance and set it on the Jsonb instance
    4. Properties file that's bootstrap on application launch
    5. A configuration singleton
  2. Which of the following annotations are JSON Binding annotations?
    1. @JsonbProperty
    2. @JsonbIgnore
    3. @JsonbNotNullable
    4. @JsonbPropertyOrder
    5. @JsonbNumberFormat
  3. Which of the following are JSON Binding strategies?
    1. PropertyVisibilityStrategy
    2. PropertyOrderStrategy
    3. PropertyNamingStrategy
    4. DateAndTimeStrategy
    5. NullPreservationStrategy
  4. What class should you implement in order to create a custom adapter?
    1. JsonbCustomAdapter
    2. JsonbSerializationAdapter
    3. JsonbDeserializationAdapter
    4. JsonAdapter
    5. None of the above
  5. How is a JSON serializer implemented and used?
    1. Implement the JsonbSerializer
    2. Pass the object to be serialized to the serialize() method of an instance of JsonbSerializer
    3. Configure an instance of JsonbConfig with an instance of JsonbSerializer
    4. Pass an instance of JsonbSerializer to @JsonbTypeSerializer
    5. None of the above

Check your answers.


Downloadable resources


Related topics


Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java development
ArticleID=1055458
ArticleTitle=Get started with the JSON Binding API, Part 3: Custom binding with JSON-B
publish-date=12132017