Статьи

EclipseLink MOXy и Java API для обработки JSON — API объектной модели

Java API для обработки JSON (JSR-353) — это стандарт Java для производства и использования JSON, который был представлен как часть Java EE 7. JSR-353 включает объектный (DOM-подобный) и потоковый (StAX-подобный) API. В этом посте я продемонстрирую первоначальную поддержку JSR-353, которую мы добавили к привязке JSON MOXy в EclipseLink 2.6. Теперь вы можете использовать MOXy для того, чтобы:

  • javax.json.JsonArrayBuilder
  • javax.json.JsonObjectBuilder

И демаршал из:

  • javax.json.JsonStructure
  • javax.json.JsonObject
  • javax.json.JsonArray

Вы можете попробовать это сегодня, используя ночную сборку EclipseLink 2.6.0:

Справочная реализация JSR-353 доступна здесь:

Модель Java

Ниже приведена простая модель клиента, которую мы будем использовать для этого поста. Обратите внимание, что для этого примера мы используем только стандартные аннотации JAXB (JSR-222) .

Клиент

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package blog.jsonp.moxy;
 
import java.util.*;
import javax.xml.bind.annotation.*;
 
@XmlType(propOrder={"id", "firstName", "lastName", "phoneNumbers"})
public class Customer {
 
    private int id;
    private String firstName;
    private String lastName;
    private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getFirstName() {
        return firstName;
    }
 
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
 
    @XmlElement(nillable=true)
    public String getLastName() {
        return lastName;
    }
 
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
 
    @XmlElement
    public List<PhoneNumber> getPhoneNumbers() {
        return phoneNumbers;
    }
 
}

Номер телефона

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package blog.jsonp.moxy;
 
import javax.xml.bind.annotation.*;
 
@XmlAccessorType(XmlAccessType.FIELD)
public class PhoneNumber {
 
    private String type;
 
    private String number;
 
    public String getType() {
        return type;
    }
 
    public void setType(String type) {
        this.type = type;
    }
 
    public String getNumber() {
        return number;
    }
 
    public void setNumber(String number) {
        this.number = number;
    }
 
}

jaxb.properties

Чтобы указать MOXy в качестве вашего JAXB-провайдера, вам нужно включить файл с именем jaxb.properties в тот же пакет, что и модель вашего домена, со следующей записью (см. Определение EclipseLink MOXy в качестве вашего JAXB-провайдера )

1
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Маршал Демо

В демонстрационном коде ниже мы будем использовать комбинацию API-интерфейсов JSR-353 и MOXy для создания JSON. JsonObjectBuilder и JsonArrayBuilder в JSR-353 используются для создания экземпляров JsonObject и JsonArray . Мы можем использовать MOXy для маршалинга этих компоновщиков, оборачивая их в экземпляры JsonObjectBuilderResult и JsonArrayBuilderResult в MOXy .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package blog.jsonp.moxy;
 
import java.util.*;
import javax.json.*;
import javax.json.stream.JsonGenerator;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.eclipse.persistence.oxm.json.*;
 
public class MarshalDemo {
 
    public static void main(String[] args) throws Exception {
        // Create the EclipseLink JAXB (MOXy) Marshaller
        Map<String, Object> jaxbProperties = new HashMap<String, Object>(2);
        jaxbProperties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
        jaxbProperties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class},
            jaxbProperties);
        Marshaller marshaller = jc.createMarshaller();
 
        // Create the JsonArrayBuilder
        JsonArrayBuilder customersArrayBuilder = Json.createArrayBuilder();
 
        // Build the First Customer
        Customer customer = new Customer();
        customer.setId(1);
        customer.setFirstName("Jane");
        customer.setLastName(null);
 
        PhoneNumber phoneNumber = new PhoneNumber();
        phoneNumber.setType("cell");
        phoneNumber.setNumber("555-1111");
        customer.getPhoneNumbers().add(phoneNumber);
 
        // Marshal the First Customer Object into the JsonArray
        JsonArrayBuilderResult result =
            new JsonArrayBuilderResult(customersArrayBuilder);
        marshaller.marshal(customer, result);
 
        // Build List of PhoneNumer Objects for Second Customer
        List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>(2);
 
        PhoneNumber workPhone = new PhoneNumber();
        workPhone.setType("work");
        workPhone.setNumber("555-2222");
        phoneNumbers.add(workPhone);
 
        PhoneNumber homePhone = new PhoneNumber();
        homePhone.setType("home");
        homePhone.setNumber("555-3333");
        phoneNumbers.add(homePhone);
 
        // Marshal the List of PhoneNumber Objects
        JsonArrayBuilderResult arrayBuilderResult = new JsonArrayBuilderResult();
        marshaller.marshal(phoneNumbers, arrayBuilderResult);
 
        customersArrayBuilder
            // Use JSR-353 APIs for Second Customer's Data
            .add(Json.createObjectBuilder()
                .add("id", 2)
                .add("firstName", "Bob")
                .addNull("lastName")
                // Included Marshalled PhoneNumber Objects
                .add("phoneNumbers", arrayBuilderResult.getJsonArrayBuilder())
             )
        .build();
 
        // Write JSON to System.out
        Map<String, Object> jsonProperties = new HashMap<String, Object>(1);
        jsonProperties.put(JsonGenerator.PRETTY_PRINTING, true);
        JsonWriterFactory writerFactory = Json.createWriterFactory(jsonProperties);
        JsonWriter writer = writerFactory.createWriter(System.out);
        writer.writeArray(customersArrayBuilder.build());
        writer.close();
    }
 
}

Выход

Ниже приведен результат запуска демоверсии маршала ( MarshalDemo ). Выделенные части (строки 2-12 и 18-25) соответствуют частям, которые были заполнены из нашей модели Java.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[
    {
        "id":1,
        "firstName":"Jane",
        "lastName":null,
        "phoneNumbers":[
            {
                "type":"cell",
                "number":"555-1111"
            }
        ]
    },
    {
        "id":2,
        "firstName":"Bob",
        "lastName":null,
        "phoneNumbers":[
            {
                "type":"work",
                "number":"555-2222"
            },
            {
                "type":"home",
                "number":"555-3333"
            }
        ]
    }
]

Демарш Демо

MOXy позволяет отменять маршализацию из JsonStructure JSR-353 ( JsonObject или JsonArray ). Для этого просто оберните J sonStructure в экземпляр JsonStructureSource в MOXy и используйте одну из операций демаршала, которая использует экземпляр Source .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package blog.jsonp.moxy;
 
import java.io.FileInputStream;
import java.util.*;
import javax.json.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.eclipse.persistence.oxm.json.JsonStructureSource;
 
public class UnmarshalDemo {
 
    public static void main(String[] args) throws Exception {
        try (FileInputStream is = new FileInputStream("src/blog/jsonp/moxy/input.json")) {
            // Create the EclipseLink JAXB (MOXy) Unmarshaller
            Map<String, Object> jaxbProperties = new HashMap<String, Object>(2);
            jaxbProperties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
            jaxbProperties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
            JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class},
                jaxbProperties);
            Unmarshaller unmarshaller = jc.createUnmarshaller();
 
            // Parse the JSON
            JsonReader jsonReader = Json.createReader(is);
 
            // Unmarshal Root Level JsonArray
            JsonArray customersArray = jsonReader.readArray();
            JsonStructureSource arraySource = new JsonStructureSource(customersArray);
            List<Customer> customers =
                (List<Customer>) unmarshaller.unmarshal(arraySource, Customer.class)
                .getValue();
            for(Customer customer : customers) {
                System.out.println(customer.getFirstName());
            }
 
            // Unmarshal Nested JsonObject
            JsonObject customerObject = customersArray.getJsonObject(1);
            JsonStructureSource objectSource = new JsonStructureSource(customerObject);
            Customer customer = unmarshaller.unmarshal(objectSource, Customer.class)
                .getValue();
            for(PhoneNumber phoneNumber : customer.getPhoneNumbers()) {
                System.out.println(phoneNumber.getNumber());
            }
        }
    }
 
}

Ввод (input.json)

Следующий вход JSON будет преобразован в JsonArray с помощью JsonReader .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[
    {
        "id":1,
        "firstName":"Jane",
        "lastName":null,
        "phoneNumbers":[
            {
                "type":"cell",
                "number":"555-1111"
            }
        ]
    },
    {
        "id":2,
        "firstName":"Bob",
        "lastName":null,
        "phoneNumbers":[
            {
                "type":"work",
                "number":"555-2222"
            },
            {
                "type":"home",
                "number":"555-3333"
            }
        ]
    }
]

Выход

Ниже приведен результат запуска демаршал демо ( UnmarshalDemo ).

1
2
3
4
Jane
Bob
555-2222
555-3333