betacode

Руководство Java JSON Processing API (JSONP)

  1. Что такое JSON?
  2. Библиотеки анализа Json
  3. Json Processing API
  4. Create Maven Project
  5. Обзор JSON-P
  6. Пример с JSON-P
  7. Пример с JsonWriter
  8. Пример с JsonParser

1. Что такое JSON?

JSON (JavaScript Object Notation) это текстовый формат, элементы которого являются набор пар ключ и значений, его значение так же может быть другим элементом (ключ и значение), значение так же может быть массивом.
Это структуные данные JSON:
{
"name" : "Tran",
"address" : "Hai Duong, Vietnam",
"phones" : [0121111111, 012222222]
}
Пример с парами вложенных ключей:
{
 "id": 111 ,
 "name":"Microsoft",
 "websites": [
    "http://microsoft.com",
    "http://msn.com",
    "http://hotmail.com"
 ],
 "address": {
    "street":"1 Microsoft Way",
    "city":"Redmond"
 }
}

2. Библиотеки анализа Json

Очень много открытых ресурсов Java библиотек, которые помогают вам анализировать данные Json. Список подобных библиотек:
  • json.org
  • Jackson
  • Google GSON
  • json-lib
  • javax json
  • json-simple
  • json-smart
  • flexjson
  • fastjson

3. Json Processing API

JSON Processing (JSR-353) API представлен в спецификации Java EE 7, это означает его библиотеки имеются на Web Server совместно с Java EE 7. Вы так же можете скачать эти библиотеки или использовать Maven.
С Maven:
<!-- http://mvnrepository.com/artifact/org.glassfish/javax.json -->
<dependency>
   <groupId>org.glassfish</groupId>
   <artifactId>javax.json</artifactId>
   <version>1.0.4</version>
</dependency>
JSON-P разделен на два основные API:
  • API Streaming (javax.json.stream),
  • JSON API Object Model (javax.json).
Streaming API используется для разъяснения браузера документов JSON сверху вниз и создает события при анализе каждого элемента в документе. Данный API подходит для разбора больших документов JSON, так как он не сохраняет данные в памяти.

API Object Model, это простые API и легче используются, так как с помощью API Streaming читается полностью документ JSON и создается объект в древовидной структуре памяти. Данный API подходит для анализа малых документов JSON.

4. Create Maven Project

Вы можете быстро создать один Maven project и объявить использование библиотеки JSON-P
Библиотека maven:
<!-- http://mvnrepository.com/artifact/org.glassfish/javax.json -->
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.json</artifactId>
    <version>1.0.4</version>
</dependency>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
 http://maven.apache.org/xsd/maven-4.0.0.xsd">

 <modelVersion>4.0.0</modelVersion>

 <groupId>org.o7planning</groupId>
 <artifactId>JSONPTutorial</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>JSONPTutorial</name>
 <url>http://maven.apache.org</url>

 <properties>
   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 </properties>

 <dependencies>


   <dependency>
     <groupId>junit</groupId>
     <artifactId>junit</artifactId>
     <version>3.8.1</version>
     <scope>test</scope>
   </dependency>
   
   <!-- http://mvnrepository.com/artifact/org.glassfish/javax.json -->
   <dependency>
       <groupId>org.glassfish</groupId>
       <artifactId>javax.json</artifactId>
       <version>1.0.4</version>
   </dependency>
   
   
 </dependencies>

</project>

5. Обзор JSON-P

Некоторые важные интерфейсы JSON API:
Интерфейс
Описание
javax.json.JsonReader
Вы можете его использовать для чтения объекта JSON или массов и получить объект JsonObject. Вы можете получить JsonReader из класса Json или JsonReaderFactory.
javax.json.JsonWriter
Вы можете использовать данный класс для записи JSON в выходной поток (Output Stream).
javax.json.stream.JsonParser
Он работает как полный анализатор, и предоставляет поток (stream) поддерживает чтение объектов JSON.
javax.json.stream.JsonGenerator
Вы можете использовать этот класс для записи объектов JSON в выходной поток (Output Stream).
javax.json.Json
Этот класс может быть использован для создания объектов обработки JSON.

6. Пример с JSON-P

Это файл данных JSON:
company.txt
{
  "id": 111 ,
  "name":"Microsoft",
  "websites": [
     "http://microsoft.com",
     "http://msn.com",
     "http://hotmail.com"
  ],
  "address":{
     "street":"1 Microsoft Way",
     "city":"Redmond"
  }
}
Заметка: Имя атрибута (attribute) должны быть в "" (ковычках), например:
  • "id": 111
Иногда документ JSON имеет именования не в ковычках, некоторые анализы JSON все равно понимают и разрешают это, но анализ JSON-P не разрешает, если вы используете Java JSON-P для анализа документа JSON с именованием не в ковычкахх, вы получите исключение:
javax.json.stream.JsonParsingException: Unexpected char 105 at (line no=xx, column no=xx, offset=xx)
Address.java
package org.o7planning.jsonptutorial.beans;

public class Address {
   
   private String street;
   private String city;

   public Address() {

   }

   public Address(String street, String city) {
       this.street = street;
       this.city = city;
   }

   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;
   }

   @Override
   public String toString() {
       return street + ", " + city;
   }
   
}
Company.java
package org.o7planning.jsonptutorial.beans;

public class Company {

   private int id;
   private String name;
   private String[] websites;
   private Address address;

   public int getId() {
       return id;
   }

   public void setId(int id) {
       this.id = id;
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public String[] getWebsites() {
       return websites;
   }

   public void setWebsites(String[] websites) {
       this.websites = websites;
   }

   public Address getAddress() {
       return address;
   }

   public void setAddress(Address address) {
       this.address = address;
   }

   @Override
   public String toString() {
       StringBuilder sb = new StringBuilder();

       sb.append("\n id:" + this.id);
       sb.append("\n name:" + this.name);
       if (this.websites != null) {
           sb.append("\n website: ");
           for (String website : this.websites) {
               sb.append(website + ", ");
           }
       }
       if (this.address != null) {
           sb.append("\n address:" + this.address.toString());
       }
       return sb.toString();
   }

}
JsonReader это объект, используемый для чтения документов JSON, вы можете получить JsonReader из класса Json или из JsonReaderFactory.
InputStream input = new FileInputStream("company.txt");
 
// Create JsonReader object from Json class.
JsonReader jsonReader1 = Json.createReader(input);

// Or from Factory
JsonReaderFactory factory = Json.createReaderFactory(null);
JsonReader jsonReader2 = factory.createReader(input);
JsonReaderExample.java
package org.o7planning.jsonptutorial;

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 org.o7planning.jsonptutorial.beans.Address;
import org.o7planning.jsonptutorial.beans.Company;

public class JsonReaderExample {
 
  public static void main(String[] args) throws IOException {
      InputStream input = new FileInputStream("company.txt");
     
      // Create JsonReader object
      JsonReader jsonReader = Json.createReader(input);
   
     
      // Get JsonObject (root object).
      JsonObject rootJSON = jsonReader.readObject();
     
      // Close resources
      jsonReader.close();
      input.close();
     
      // Create empty Company object.
      Company company = new Company();
     
      company.setId(rootJSON.getInt("id"));
      company.setName(rootJSON.getString("name"));
     
     
      // Reading websites array from json
      JsonArray jsonArray = rootJSON.getJsonArray("websites");
      String[] websites = new String[jsonArray.size()];
     
      int index = 0;
      for(JsonValue value : jsonArray){
          websites[index++] = value.toString() ;
      }
      company.setWebsites(websites);
     
      // Reading inner object from json object.
      JsonObject addressJSON = rootJSON.getJsonObject("address");
      Address address = new Address();
      address.setStreet(addressJSON.getString("street"));
      address.setCity(addressJSON.getString("city"));
   
      company.setAddress(address);
     
      // Print out information
      System.out.println(company);
     
  }

}
Запуск примера:

7. Пример с JsonWriter

JsonWriterExample.java
package org.o7planning.jsonptutorial;

import java.io.File;
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;

import org.o7planning.jsonptutorial.beans.Address;
import org.o7planning.jsonptutorial.beans.Company;

public class JsonWriterExample {

  public static void main(String[] args) throws FileNotFoundException {

      Company company = createCompany();

      // Object Builder
      JsonObjectBuilder companyBuilder = Json.createObjectBuilder();
     
      // Object Builder
      JsonObjectBuilder addressBuilder = Json.createObjectBuilder();
     
      // Array Builder
      JsonArrayBuilder websitesBuilder = Json.createArrayBuilder();

      for (String website : company.getWebsites()) {
          websitesBuilder.add(website);
      }

      Address address = company.getAddress();
      addressBuilder.add("street", address.getStreet()).add("city", address.getCity() );

      companyBuilder.add("id", company.getId()).add("name", company.getName() );

      companyBuilder.add("websites", websitesBuilder);
      companyBuilder.add("address", addressBuilder);

      // Root JsonObject
      JsonObject rootJSONObject = companyBuilder.build();

      System.out.println("Root JsonObject: " + rootJSONObject);

      // Write to file
      File outFile= new File("C:/test/company2.txt");
      outFile.getParentFile().mkdirs();
     
      OutputStream os = new FileOutputStream(outFile);
      JsonWriter jsonWriter = Json.createWriter(os);
     
      jsonWriter.writeObject(rootJSONObject);
      jsonWriter.close();
  }

  public static Company createCompany() {

      Company company = new Company();
      company.setId(123);
      company.setName("Apple");

      String[] websites = { "http://apple.com"};
      company.setWebsites(websites);

      Address address = new Address();
      address.setCity("Cupertino");
      address.setStreet("1 Infinite Loop");

      company.setAddress(address);

      return company;
  }
 
}
Запуск примера:

8. Пример с JsonParser

До этого вы работали с JsonReader, чтобы прочитать содержимое file json, полное содержание Json является объектом и хранится в памяти, этот способ подходит только когда вы работаете с малым документом Json. В случае работы с большим документом вам стоит использовать JsonParser, чтобы анализировать документ Json. JsonParser работает примерно так же как XML в SAX. JsonParser не сохраняет прочитанные данные в памяти.
В коде вызывает метод next() чтобы JsonParser анализировал следующий элемент Json, он генерирует события после анализа каждого элемента. Данный парсер может генерировать следующие события:
  • START_OBJECT
  • END_OBJECT
  • START_ARRAY
  • END_ARRAY
  • KEY_NAME
  • VALUE_STRING
  • VALUE_NUMBER
  • VALUE_TRUE
  • VALUE_FALSE
  • VALUE_NULL.
Исходя из имени испущенного события, и имени анализируемого элемента, вы можете узнать место анализа и получить оттуда значения.
Возможные методы использования в данном случае:
  • getString()
  • getInt()
  • ....
Например:
JsonParserExample.java
package org.o7planning.jsonptutorial;

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 org.o7planning.jsonptutorial.beans.Address;
import org.o7planning.jsonptutorial.beans.Company;

public class JsonParserExample {

    public static void main(String[] args) throws IOException {
        InputStream inputStream = new FileInputStream("company.txt");

        JsonParser jsonParser = Json.createParser(inputStream);


        // Create objects, their fields will be assigned values
        // each time the value is found in the events.
        Company company = new Company();
        Address address = new Address();
        
        List<String> websitesList = new ArrayList<String>();

        // Key name of JSON
        String keyName = null;
        
        while (jsonParser.hasNext()) {
            JsonParser.Event event = jsonParser.next();
            switch (event) {
            case KEY_NAME:
                keyName = jsonParser.getString();
                break;
            case VALUE_STRING:
                setStringValues(company, address, keyName, jsonParser.getString(), websitesList);
                break;
            case VALUE_NUMBER:
                setNumberValues(company, address, keyName, jsonParser.getInt());
                break;
            default:
                // No need..
            }
        }
        company.setAddress(address);
        String[] websites = new String[websitesList.size()];
        websitesList.toArray(websites);
        company.setWebsites(websites);

        // Print out
        System.out.println(company);        
        inputStream.close();
        jsonParser.close();
    }

    private static void setNumberValues(Company company, Address address, String keyName, int value) {
        if (keyName.equals("id")) {
            company.setId(value);
        } else {
            System.out.println("Unknown Key:" + keyName);
        }
    }

    private static void setStringValues(Company company, Address address, String keyName, String value,
            List<String> websiteList) {
        if (keyName.equals("name")) {
            company.setName(value);
        } else if (keyName.equals("street")) {
            address.setStreet(value);
        } else if (keyName.equals("city")) {
            address.setCity(value);
        } else if (keyName.equals("websites")) {
            websiteList.add(value);
        } else {
            System.out.println("Unknown Key=" + keyName);
        }
    }

}
Запуск примера: