JSON (JavaScript Object Notation) is text-based lightweight technology. Nowadays it is a dominant and much-expected way of communication in the form of key-value pairs. It is an easier way of transmitting data as it is having nice formatted way. We can nest the objects and also can provide JSON arrays also.
Implementation steps for a maven project
“jsonp” is the reference implementation for Java JSON Processing API. In a maven project, the required dependency has to be specified in pom.xml
XML
< dependency > < groupId >org.glassfish</ groupId > < artifactId >javax.json</ artifactId > < version >1.0.2</ version > </ dependency > |
JSON processing can be done in 2 ways. They are provided by JSON API
Object Model API | Features are similar to DOM Parser and it holds good for small objects. |
Streaming API | Features are similar to StAX Parser and it holds good for large objects. Here we no need to keep the whole object in memory. |
Interfaces of Java JSON API:
javax.json.JsonReader | To read a JsonObject or an array of JsonObject JsonReader is used. It is available from JSON class or JsonReaderFactory |
javax.json.JsonWriter | Write JSON object to the output stream |
javax.json.stream.JsonParser | Working functionality is a pull parser type and can provide support for reading JSON objects in a streaming way. |
javax.json.stream.JsonGenerator | To write JSON objects in a streaming way. |
javax.json.Json | This class has a variety of methods for creating these objects and their factories. |
javax.json.JsonObject | This is the representation of immutable JSON object value. |
Let us see the above functionalities one by one. First let us take a sample JSON object. It may be stored in a file named “gfgwriterfile.txt”. Key-value pair, the data is available.
Example: “id” is the key and its value is 123
{ "id":123, "writerName":"GeekWriterA", "status":true, "address":{ "street":"MG Road", "city":"Bangalore", "zipcode":560100 }, "phoneNumbers":[1122334455, 1234567890], "role":"HitechWriter" }
We need to have Java bean classes to represent the above JSON format. Let us have 2 Java bean classes namely “Address.java” and “GFGWriter.java”
Address.java
Java
public class Address { // attributes for address private String street; private String city; private int zipcode; // necessary getters and setters public String getStreet() { return street; } public void setStreet(String street) { this .street = street; } public String getCity() { return city; } public void setCity(String city) { this .city = city; } public int getZipcode() { return zipcode; } public void setZipcode( int zipcode) { this .zipcode = zipcode; } @Override public String toString() { return getStreet() + ", " + getCity() + ", " + getZipcode(); } } |
We are going to use Address.java inside “GFGWriter.java”
GFGWriter.java
Java
import java.util.Arrays; public class GFGWriter { private int id; private String writerName; private boolean status; private Address address; private long [] phoneNumbers; private String role; public int getId() { return id; } public void setId( int id) { this .id = id; } public String getWriterName() { return writerName; } public void setWriterName(String writerName) { this .writerName = writerName; } public boolean getStatus() { return status; } public void setStatus( boolean status) { this .status = status; } public Address getAddress() { return address; } public void setAddress(Address address) { this .address = address; } public long [] getPhoneNumbers() { return phoneNumbers; } public void setPhoneNumbers( long [] phoneNumbers) { this .phoneNumbers = phoneNumbers; } public String getRole() { return role; } public void setRole(String role) { this .role = role; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append( "***** GFG Portal Writer Details *****\n" ); sb.append( "ID=" + getId() + "\n" ); sb.append( "Writer Name=" + getWriterName() + "\n" ); sb.append( "Status=" + getStatus() + "\n" ); sb.append( "Role=" + getRole() + "\n" ); sb.append( "Phone Numbers=" + Arrays.toString(getPhoneNumbers()) + "\n" ); sb.append( "Address=" + getAddress()); sb.append( "\n*****************************" ); return sb.toString(); } } |
toString() method can be overridden as per our requirement and here, just a human-readable way it is written. Now let us see by using Java bean methods, let us see how to read the Java JSON
GFGWriterJSONReader.java (Here from gfgwriter.txt, we are going to read and display the data)
Java
import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import javax.json.Json; import javax.json.JsonArray; import javax.json.JsonObject; import javax.json.JsonReader; import javax.json.JsonValue; import com.gfg.model.Address; import com.gfg.model.GFGWriter; public class GFGWriterJSONReader { public static final String JSON_FILE= "gfgwriter.txt" ; public static void main(String[] args) throws IOException { InputStream fis = new FileInputStream(JSON_FILE); // create JsonReader object JsonReader jsonReader = Json.createReader(fis); // get JsonObject from JsonReader JsonObject jsonObject = jsonReader.readObject(); // we can close IO resource and JsonReader now jsonReader.close(); fis.close(); // Retrieve data from JsonObject and create Employee bean GFGWriter gfgWriter = new GFGWriter(); gfgWriter.setId(jsonObject.getInt( "id" )); gfgWriter.setWriterName(jsonObject.getString( "writerName" )); gfgWriter.setStatus(jsonObject.getBoolean( "status" )); gfgWriter.setRole(jsonObject.getString( "role" )); // reading arrays from json JsonArray jsonArray = jsonObject.getJsonArray( "phoneNumbers" ); long [] numbers = new long [jsonArray.size()]; int index = 0 ; for (JsonValue value : jsonArray){ numbers[index++] = Long.parseLong(value.toString()); } gfgWriter.setPhoneNumbers(numbers); // reading inner object from json object JsonObject innerJsonObject = jsonObject.getJsonObject( "address" ); Address address = new Address(); address.setStreet(innerJsonObject.getString( "street" )); address.setCity(innerJsonObject.getString( "city" )); address.setZipcode(innerJsonObject.getInt( "zipcode" )); gfgWriter.setAddress(address); // print GFGWriter bean information System.out.println(gfgWriter); } } |
JsonReaderFactory implements Factory Design Pattern. Implementation is straightforward. On running the file, we will get the output as follows
Let us see the ways to write the JSON
GFGWriterCreation.java
Java
import com.gfg.model.Address; import com.gfg.model.GFGWriter; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.OutputStream; import javax.json.Json; import javax.json.JsonArrayBuilder; import javax.json.JsonObject; import javax.json.JsonObjectBuilder; import javax.json.JsonWriter; public class GFGWriterCreation { public static void main(String[] args) throws FileNotFoundException { GFGWriter gfgWriter = createGFGWriter(); JsonObjectBuilder writerBuilder = Json.createObjectBuilder(); JsonObjectBuilder addressBuilder = Json.createObjectBuilder(); JsonArrayBuilder phoneNumberBuilder = Json.createArrayBuilder(); for ( long phone : gfgWriter.getPhoneNumbers()) { phoneNumberBuilder.add(phone); } addressBuilder .add( "street" , gfgWriter.getAddress().getStreet()) .add( "city" , gfgWriter.getAddress().getCity()) .add( "zipcode" , gfgWriter.getAddress().getZipcode()); writerBuilder.add( "id" , gfgWriter.getId()) .add( "writerName" , gfgWriter.getWriterName()) .add( "status" , gfgWriter.getStatus()) .add( "role" , gfgWriter.getRole()); writerBuilder.add( "phoneNumbers" , phoneNumberBuilder); writerBuilder.add( "address" , addressBuilder); JsonObject gfgWriterJsonObject = writerBuilder.build(); System.out.println( "GFGWriter JSON String\n" + gfgWriterJsonObject); // write to file OutputStream os = new FileOutputStream( "gfgwriter.txt" ); JsonWriter jsonWriter = Json.createWriter(os); jsonWriter.writeObject(gfgWriterJsonObject); jsonWriter.close(); } public static GFGWriter createGFGWriter() { GFGWriter gfgWriter = new GFGWriter(); gfgWriter.setId( 100 ); gfgWriter.setWriterName( "GeekA" ); gfgWriter.setStatus( false ); gfgWriter.setPhoneNumbers( new long [] { 123456 , 987654 }); gfgWriter.setRole( "Beginner" ); Address add = new Address(); add.setCity( "Bangalore" ); add.setStreet( "MG Road" ); add.setZipcode( 560100 ); gfgWriter.setAddress(add); return gfgWriter; } } |
The JSON object is also getting saved in the ‘gfgwriter.txt’ file via the above code. JsonObjectBuilder implements builder pattern. On running the above program, we will be getting the output as
Java JSON Parser Example
GFGWriterJSONParser.java
Java
import com.gfg.model.Address; import com.gfg.model.GFGWriter; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import javax.json.Json; import javax.json.stream.JsonParser; import javax.json.stream.JsonParser.Event; public class GFGWriterJSONParser { public static final String FILE_NAME = "gfgwriterfile.txt" ; public static void main(String[] args) throws IOException { InputStream fis = new FileInputStream(FILE_NAME); JsonParser jsonParser = Json.createParser(fis); GFGWriter gfgWriter = new GFGWriter(); Address address = new Address(); String keyName = null ; List<Long> phoneNums = new ArrayList<Long>(); while (jsonParser.hasNext()) { Event event = jsonParser.next(); switch (event) { case KEY_NAME: keyName = jsonParser.getString(); break ; case VALUE_STRING: setStringValues(gfgWriter, address, keyName, jsonParser.getString()); break ; case VALUE_NUMBER: setNumberValues(gfgWriter, address, keyName, jsonParser.getLong(), phoneNums); break ; case VALUE_FALSE: setBooleanValues(gfgWriter, address, keyName, false ); break ; case VALUE_TRUE: setBooleanValues(gfgWriter, address, keyName, true ); break ; case VALUE_NULL: // don't set anything break ; default : // we are not looking for other events } } gfgWriter.setAddress(address); long [] nums = new long [phoneNums.size()]; int index = 0 ; for (Long l : phoneNums) { nums[index++] = l; } gfgWriter.setPhoneNumbers(nums); System.out.println(gfgWriter); // close resources fis.close(); jsonParser.close(); } private static void setNumberValues(GFGWriter gfgWriter, Address address, String keyName, long value, List<Long> phoneNumbers) { switch (keyName) { case "zipcode" : address.setZipcode(( int )value); break ; case "id" : gfgWriter.setId(( int )value); break ; case "phoneNumbers" : phoneNumbers.add(value); break ; default : System.out.println( "Unknown element with key=" + keyName); } } private static void setBooleanValues(GFGWriter gfgWriter, Address address, String key, boolean value) { if ( "status" .equals(key)) { gfgWriter.setStatus(value); } else { System.out.println( "Unknown element with key=" + key); } } private static void setStringValues(GFGWriter gfgWriter, Address address, String key, String value) { switch (key) { case "writerName" : gfgWriter.setWriterName(value); break ; case "role" : gfgWriter.setRole(value); break ; case "city" : address.setCity(value); break ; case "street" : address.setStreet(value); break ; default : System.out.println( "Unkonwn Key=" + key); } } } |
On running, we will get the same output as JSON Reader. That is similar output what we get during JSON reader. Complexity will be more if we need to parse complex JSON. Next, let us see JsonGeneratorExample
GFGWriterJSONGenerator.java
Java
import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import javax.json.Json; import javax.json.stream.JsonGenerator; import com.gfg.model.GFGWriter; public class GFGWriterJSONGenerator { public static void main(String[] args) throws IOException { OutputStream fos = new FileOutputStream( "gfgwriter_stream.txt" ); JsonGenerator jsonGenerator = Json.createGenerator(fos); GFGWriter gfgWriter = GFGWriterCreation.createGFGWriter(); jsonGenerator.writeStartObject(); // { jsonGenerator.write( "id" , gfgWriter.getId()); // "id":100 jsonGenerator.write( "writerName" , gfgWriter.getWriterName()); jsonGenerator.write( "role" , gfgWriter.getRole()); jsonGenerator.write( "status" , gfgWriter.getStatus()); jsonGenerator.writeStartObject( "address" ) // start of address object .write( "street" , gfgWriter.getAddress().getStreet()) .write( "city" ,gfgWriter.getAddress().getCity()) .write( "zipcode" ,gfgWriter.getAddress().getZipcode()) .writeEnd(); // end of address object jsonGenerator.writeStartArray( "phoneNumbers" ); // start of phone num array for ( long num : gfgWriter.getPhoneNumbers()){ jsonGenerator.write(num); } jsonGenerator.writeEnd(); // end of phone num array jsonGenerator.writeEnd(); // } jsonGenerator.close(); } } |
On running the above program, we can see the contents written in “gfgwriter_stream.txt”, “JsonGenerator” is very easy to use and its specialty is it provides good performance for large data.