Package org.openntf.jsonbeanx

The JsonBeanX classes can be used by IBM Notes/Domino XPages developers to convert between JSON strings and Java beans.

See:
          Description

Class Summary
J2BConverter The J2BConverter class can do the following:
J2BSettings Settings used by J2BConverter when you are converting between JSON strings and Java beans.
 

Exception Summary
J2BException An Exception thrown by the J2BConverter.
 

Package org.openntf.jsonbeanx Description

The JsonBeanX classes can be used by IBM Notes/Domino XPages developers to convert between JSON strings and Java beans. It uses the IBM Commons JsonParser to do part of the conversion, so if you want to use this outside of an XPages environment you must include the com.ibm.commons library with your project to use the com.ibm.commons.util.io.json classes.

By default, the JSON parser can read JSON strings and output Lists and Maps, and it can take Lists and Maps and convert them to JSON. The JsonBeanX library allows you to convert JSON directly to a Java bean, or a Java bean directly to JSON.

Some ground rules:

Converting JSON to Java Beans

Given the following JSON:

{ "title":"Gone With The Breeze", 
  "studio":"NGN",
  "awards": ["Best Picture","Best Actress","Best Actor"],
  "revenue": {"unadjusted":200000000,"adjusted":1750000000},
  "lastUpdated":"2016-01-12",
  "year":1939
 }

We can map this to the following two Java bean classes:

public class Movie {
	String title;
	String studio;
	String[] awards;
	Revenue revenue; 
	String lastUpdated;
	int year;

	public Movie() {}
 	public String getTitle() { return this.title; }
 	public void setTitle(String title) { this.title = title; }
 	public String getStudio() { return this.studio; }
 	public void setStudio(String studio) { this.studio = studio; }
 	public String[] getAwards() { return this.awards; }
 	public void setAwards(String[] awards) { this.awards = awards; }
 	public Revenue getRevenue() { return this.revenue; }
 	public void setRevenue(Revenue revenue) { this.revenue = revenue; }
 	public String getLastUpdated() { return this.lastUpdated; }
 	public void setLastUpdated(Date lastUpdated) { this.lastUpdated = lastUpdated; }
 	public int getYear() { return this.year; }
 	public void setYear(int year) { this.year = year; }
}

and

public class Revenue {
	long unadjusted;
	long adjusted;

	public Revenue() {}
	public long getUnadjusted() { return this.unadjusted; }
 	public void setUnadjusted(long unadjusted) { this.unadjusted = unadjusted; }
 	public long getAdjusted() { return this.adjusted; }
 	public void setAdjusted(long adjusted) { this.adjusted = adjusted; }
 }

This is easily done using the following code:

List<Movie> movies = J2BConverter.jsonToBean(Movie.class, json);

However, in this case the date format won't map correctly. Dates in JSON are always Strings (there is no JSON date type), so you need to write this additional code:

J2BSettings settings = new J2BSettings();
settings.setDateFormat("yyyy-MM-dd");
List<Movie> movies = J2BConverter.jsonToBean(Movie.class, json, settings);

Sometimes JSON will include a prefix before class data, like this:

{"movie": {"title":"Gone With The Breeze", 
  "studio":"NGN",
  "awards": ["Best Picture","Best Actress","Best Actor"],
  "revenue": {"unadjusted":200000000,"adjusted":1750000000},
  "lastUpdated":"2016-01-12",
  "year":1939
 }}

In this case you would need to either use a wrapper for Movie.class like this:

public class MovieWrapper {
	Movie movie;

	public MovieWrapper() {}
	public Movie getMovie() { return this.movie; }
 	public void setMovie(Movie movie) { this.movie = movie; }
 }

and call jsonToBean(MovieWrapper.class, json, settings), or you would need to specify a classname prefix for Movie.class like this:

J2BSettings settings = new J2BSettings();
settings.setDateFormat("yyyy-MM-dd");
settings.addJSONClassPrefix(Movie.class, "movie");
List<Movie> movies = J2BConverter.jsonToBean(Movie.class, json, settings);

A few other things:

Converting Java Beans to JSON

To convert a Java bean to JSON, do the following:

J2BSettings settings = new J2BSettings();
settings.setDateFormat("yyyy-MM-dd");
String json = J2BConverter.beanToJson(movie, settings);

The J2BSettings parameter is optional; in this case we need it because of the Date value. By default it will output the date in the system format, which might not be what you want.

Take special note of settings that can cause parsing to fail if certain conditions are not met: setMappingFailureFatal and addRequiredField. These can be very useful for JSON validation because they will cause beanToJson to throw an Exception if JSON fields cannot be mapped or if specific JSON fields are not present.

Creating Stub Class Code

createStubClasses can also suggest a Java bean class structure for you based on a JSON string, if you need to parse some JSON you have never used before. For the JSON example above, a call to:

String javaBeanSuggestion = J2BConverter.createStubClasses(json);

results in the following:

public class Revenue {
	Double unadjusted; 	// 2.0E8
	Double adjusted; 	// 1.75E9

	public Revenue() {}
	public Double getUnadjusted() { return this.unadjusted; }
 	public void setUnadjusted(Double unadjusted) { this.unadjusted = unadjusted; }
 	public Double getAdjusted() { return this.adjusted; }
 	public void setAdjusted(Double adjusted) { this.adjusted = adjusted; }
 }

public class JsonData {
	String studio; 	// NGN
	List<String> awards; 	// [Best Picture, Best Actress, Best Actor]
	String title; 	// Gone With The Breeze
	Revenue revenue; 
	Double year; 	// 1939.0
	String lastUpdated; 	// 2016-01-14

	public JsonData() {}
 	public String getStudio() { return this.studio; }
 	public void setStudio(String studio) { this.studio = studio; }
 	public List<String> getAwards() { return this.awards; }
 	public void setAwards(List<String> awards) { this.awards = awards; }
 	public String getTitle() { return this.title; }
 	public void setTitle(String title) { this.title = title; }
 	public Revenue getRevenue() { return this.revenue; }
 	public void setRevenue(Revenue revenue) { this.revenue = revenue; }
 	public Double getYear() { return this.year; }
 	public void setYear(Double year) { this.year = year; }
 	public String getLastUpdated() { return this.lastUpdated; }
 	public void setLastUpdated(Date lastUpdated) { this.lastUpdated = lastUpdated; }
 }

Items of note:

You can adjust those items as needed or leave them as-is.

Also, the class fields have comments indicating what the data looked like when it was parsed, so you can make a better guess at what the field types should be.

createStubClasses isn't perfect, but it will help get you started. Specifically, if it encounters a List of JSON objects and the objects in the list have different structures, only the first object in the list will be used for class generation, and if multiple instances of the same nested class are encountered they will be output multiple times. So please check the results and don't use them blindly.

Normally you want to copy all the stub classes into separate class files for use by your code. If you decide you want to copy them into an existing class as inner classes, that will work but only if you make them static inner classes. Inner classes that aren't static cannot be instantiated directly from outside their parent class, and the J2BConverter won't be able to use them.

Why Use This Instead of GSON or Jackson?

The gson and Jackson libraries will also do this sort of JSON-to-bean mapping, and they are much more "complete" in terms of options and support. So why use this library?

The advantages of JsonBeanX are:

It's up to you though. Options are good.


Copyright (C) 2015-16 Julian Robichaux

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.