Merge pull request #314 from aguibert/test-doc-examples

Add tests for examples shown in JSON-B documentation
diff --git a/src/test/java/org/eclipse/yasson/documented/DocumentationExampleTest.java b/src/test/java/org/eclipse/yasson/documented/DocumentationExampleTest.java
new file mode 100644
index 0000000..ac4f751
--- /dev/null
+++ b/src/test/java/org/eclipse/yasson/documented/DocumentationExampleTest.java
@@ -0,0 +1,576 @@
+package org.eclipse.yasson.documented;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbBuilder;
+import javax.json.bind.JsonbConfig;
+import javax.json.bind.adapter.JsonbAdapter;
+import javax.json.bind.annotation.JsonbCreator;
+import javax.json.bind.annotation.JsonbDateFormat;
+import javax.json.bind.annotation.JsonbNillable;
+import javax.json.bind.annotation.JsonbNumberFormat;
+import javax.json.bind.annotation.JsonbProperty;
+import javax.json.bind.annotation.JsonbTransient;
+import javax.json.bind.serializer.DeserializationContext;
+import javax.json.bind.serializer.JsonbDeserializer;
+import javax.json.bind.serializer.JsonbSerializer;
+import javax.json.bind.serializer.SerializationContext;
+import javax.json.stream.JsonGenerator;
+import javax.json.stream.JsonParser;
+
+import org.junit.Test;
+
+/**
+ * Contains tests from http://json-b.net/docs/user-guide.html
+ */
+public class DocumentationExampleTest {
+
+    public static class Dog {
+        public String name;
+        public int age;
+        public boolean bitable;
+    }
+
+    @Test
+    public void testMappingExample() {
+        // Create a dog instance
+        Dog dog = new Dog();
+        dog.name = "Falco";
+        dog.age = 4;
+        dog.bitable = false;
+
+        // Create Jsonb and serialize
+        Jsonb jsonb = JsonbBuilder.create();
+        String result = jsonb.toJson(dog);
+        assertEquals("{\"age\":4,\"bitable\":false,\"name\":\"Falco\"}", result);
+
+        // Deserialize back
+        dog = jsonb.fromJson("{\"name\":\"Falco\",\"age\":4,\"bites\":false}", Dog.class);
+        assertEquals("Falco", dog.name);
+        assertEquals(4, dog.age);
+        assertEquals(false, dog.bitable);
+    }
+
+    @Test
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public void testMappingCollection() {
+        Dog falco = new Dog();
+        falco.name = "Falco";
+        falco.age = 4;
+        Dog cassidy = new Dog();
+        cassidy.name = "Cassidy";
+        cassidy.age = 5;
+
+        // List of dogs
+        List dogs = new ArrayList();
+        dogs.add(falco);
+        dogs.add(cassidy);
+
+        // Create Jsonb and serialize
+        Jsonb jsonb = JsonbBuilder.create();
+        String result = jsonb.toJson(dogs);
+        assertEquals(
+                "[{\"age\":4,\"bitable\":false,\"name\":\"Falco\"},{\"age\":5,\"bitable\":false,\"name\":\"Cassidy\"}]",
+                result);
+
+        // We can also deserialize back into a raw collection, but since there is no way
+        // to infer a type here,
+        // the result will be a list of java.util.Map instances with string keys.
+        dogs = jsonb.fromJson(result, ArrayList.class);
+        assertEquals(2, dogs.size());
+        assertEquals("Falco", ((Map) dogs.get(0)).get("name"));
+        assertEquals("Cassidy", ((Map) dogs.get(1)).get("name"));
+        // assertEquals(4, ((Map) dogs.get(0)).get("age")); // TODO should these
+        // actually be BigDecimals?
+        // assertEquals(5, ((Map) dogs.get(1)).get("age"));
+    }
+
+    @SuppressWarnings("serial")
+    @Test
+    public void testMappingGenericCollection() {
+        Dog falco = new Dog();
+        falco.name = "Falco";
+        falco.age = 4;
+        Dog cassidy = new Dog();
+        cassidy.name = "Cassidy";
+        cassidy.age = 5;
+
+        // List of dogs
+        List<Dog> dogs = new ArrayList<>();
+        dogs.add(falco);
+        dogs.add(cassidy);
+
+        // Create Jsonb and serialize
+        Jsonb jsonb = JsonbBuilder.create();
+        String result = jsonb.toJson(dogs);
+        assertEquals(
+                "[{\"age\":4,\"bitable\":false,\"name\":\"Falco\"},{\"age\":5,\"bitable\":false,\"name\":\"Cassidy\"}]",
+                result);
+
+        // Deserialize back
+        dogs = jsonb.fromJson(result, new ArrayList<Dog>() {
+        }.getClass().getGenericSuperclass());
+        assertEquals(2, dogs.size());
+        assertEquals("Falco", dogs.get(0).name);
+        assertEquals("Cassidy", dogs.get(1).name);
+    }
+
+    @Test
+    public void testFormattedOutput() {
+        Dog pojo = new Dog();
+        pojo.name = "Falco";
+        pojo.age = 4;
+
+        // Create custom configuration with formatted output
+        JsonbConfig config = new JsonbConfig().withFormatting(true);
+
+        // Create Jsonb with custom configuration
+        Jsonb jsonb = JsonbBuilder.create(config);
+
+        // Use it!
+        String result = jsonb.toJson(pojo);
+        assertEquals("\n" + 
+                "{\n" + 
+                "    \"age\": 4,\n" + 
+                "    \"bitable\": false,\n" + 
+                "    \"name\": \"Falco\"\n" + 
+                "}", result);
+    }
+    
+    public static class Person1 {
+        @JsonbProperty("person-name")
+        public String name;
+        public String profession;
+    }
+    
+    @Test
+    public void testChangingPropertyNames1() {
+        Person1 p = new Person1();
+        p.name = "Jason Bourne";
+        p.profession = "Super Agent";
+        Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withFormatting(true));
+        String result = jsonb.toJson(p);
+        assertEquals("\n" +
+                "{\n" + 
+                "    \"person-name\": \"Jason Bourne\",\n" + 
+                "    \"profession\": \"Super Agent\"\n" + 
+                "}", result);
+    }
+    
+    public class Person2 {
+        private String name;
+        private String profession;
+
+        @JsonbProperty("person-name")
+        public String getName() {
+            return name;
+        }
+
+        public String getProfession() {
+            return profession;
+        }
+
+        // public setters ...
+        public void setName(String name) {
+            this.name = name;
+        }
+        public void setProfession(String profession) {
+            this.profession = profession;
+        }
+    }
+    
+    @Test
+    public void testChangingPropertyNames2() {
+        Person2 p = new Person2();
+        p.name = "Jason Bourne";
+        p.profession = "Super Agent";
+        Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withFormatting(true));
+        String result = jsonb.toJson(p);
+        assertEquals("\n" +
+                "{\n" + 
+                "    \"person-name\": \"Jason Bourne\",\n" + 
+                "    \"profession\": \"Super Agent\"\n" + 
+                "}", result);
+    }
+    
+    public static class Person3 {
+        private String name;
+
+        @JsonbProperty("name-to-write")
+        public String getName() {
+            return name;
+        }
+
+        @JsonbProperty("name-to-read")
+        public void setName(String name) {
+            this.name = name;
+        }
+    }
+    
+    @Test
+    public void testChangingPropertyNames3() {
+        Person3 p = new Person3();
+        p.name = "Jason Bourne";
+        Jsonb jsonb = JsonbBuilder.create();
+        String result = jsonb.toJson(p);
+        assertEquals("{\"name-to-write\":\"Jason Bourne\"}", result);
+        
+        String json = "{\"name-to-read\":\"Jason Bourne\"}";
+        Person3 after = jsonb.fromJson(json, Person3.class);
+        assertEquals("Jason Bourne", after.name);
+    }
+    
+    public static class Person4 { // TODO: a non-static class results in an NPE
+        @JsonbTransient
+        private String name;
+
+        private String profession;
+
+        // public getters/setters ...
+        public String getName() {
+            return name;
+        }
+        public void setName(String name) {
+            this.name = name;
+        }
+        public String getProfession() {
+            return this.profession;
+        }
+        public void setProfession(String profession) {
+            this.profession = profession;
+        }
+    }
+    
+    @Test
+    public void testIgnoringProperties() {
+        Person4 p = new Person4();
+        p.name = "Jason Bourne";
+        p.profession = "Super Agent";
+        Jsonb jsonb = JsonbBuilder.create();
+        String result = jsonb.toJson(p);
+        assertEquals("{\"profession\":\"Super Agent\"}", result);
+        
+        String json = "{\"profession\":\"Super Agent\"}";
+        Person4 after = jsonb.fromJson(json, Person4.class);
+        assertEquals("Super Agent", after.profession);
+        assertNull(after.name);
+    }
+    
+    @JsonbNillable
+    public class Person5 {
+        private String name;
+        private String profession;
+
+        // public getters/setters ...
+        public String getName() {
+            return name;
+        }
+        public void setName(String name) {
+            this.name = name;
+        }
+        public String getProfession() {
+            return profession;
+        }
+        public void setProfession(String profession) {
+            this.profession = profession;
+        }
+    }
+    
+    @Test
+    public void testNullHandling1() {
+        Person5 p = new Person5();
+        Jsonb jsonb = JsonbBuilder.create();
+        String result = jsonb.toJson(p);
+        assertEquals("{\"name\":null,\"profession\":null}", result);
+    }
+    
+    public class Person6 {
+        @JsonbProperty(nillable=true)
+        private String name;
+
+        private String profession;
+
+        // public getters/setters ...
+        public String getName() {
+            return name;
+        }
+        public void setName(String name) {
+            this.name = name;
+        }
+        public String getProfession() {
+            return profession;
+        }
+        public void setProfession(String profession) {
+            this.profession = profession;
+        }
+    }
+    
+    @Test
+    public void testNullHandling2() {
+        Person6 p = new Person6();
+        Jsonb jsonb = JsonbBuilder.create();
+        String result = jsonb.toJson(p);
+        assertEquals("{\"name\":null}", result);
+    }
+    
+    public static class Person {
+        public String name;
+        public String profession;
+    }
+
+    @Test
+    public void testNullHandling3() {
+        Person p = new Person();
+        Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withNullValues(true));
+        String result = jsonb.toJson(p);
+        assertEquals("{\"name\":null,\"profession\":null}", result);
+    }
+    
+    public static class Person8 { // TODO: obscure error here if non-static
+        public final String name;
+        public String profession;
+
+        @JsonbCreator
+        public Person8(@JsonbProperty("name") String name) {
+            this.name = name;
+        }
+    }
+    
+    @Test
+    public void testCustomInstantiation() {
+        Jsonb jsonb = JsonbBuilder.create();
+        Person8 p = jsonb.fromJson("{\"name\":\"Jason Bourne\"}", Person8.class);
+        assertEquals("Jason Bourne", p.name);
+    }
+    
+    public static class Person9 {
+        public String name;
+
+        @JsonbDateFormat("dd.MM.yyyy")
+        public LocalDate birthDate;
+
+        @JsonbNumberFormat("#0.00")
+        public BigDecimal salary;
+    }
+    
+    @Test
+    public void testDateNumberFormats1() {
+        Person9 p = new Person9();
+        p.name = "Jason Bourne";
+        p.birthDate = LocalDate.of(1999, 8, 7);
+        p.salary = new BigDecimal("123.45678");
+        Jsonb jsonb = JsonbBuilder.create();
+        String json = jsonb.toJson(p);
+        assertEquals("{\"birthDate\":\"07.08.1999\",\"name\":\"Jason Bourne\",\"salary\":\"123.46\"}", json);
+        
+        Person9 after = jsonb.fromJson("{\"birthDate\":\"07.08.1999\",\"name\":\"Jason Bourne\",\"salary\":\"123.46\"}", Person9.class);
+        assertEquals(p.name, after.name);
+        assertEquals(p.birthDate, after.birthDate);
+        assertEquals(new BigDecimal("123.46"), after.salary);
+    }
+    
+    public static class Person10 {
+        public String name;
+
+        public LocalDate birthDate;
+
+        public BigDecimal salary;
+    }
+    
+    @Test
+    public void testDateNumberFormats2() {
+        Person10 p = new Person10();
+        p.name = "Jason Bourne";
+        p.birthDate = LocalDate.of(1999, 8, 7);
+        p.salary = new BigDecimal("123.45678");
+        Jsonb jsonb = JsonbBuilder.create(new JsonbConfig()//
+                .withDateFormat("dd.MM.yyyy", null)); // TODO: why no withNumberFormat?
+        String json = jsonb.toJson(p);
+        assertEquals("{\"birthDate\":\"07.08.1999\",\"name\":\"Jason Bourne\",\"salary\":123.45678}", json);
+        
+        Person9 after = jsonb.fromJson("{\"birthDate\":\"07.08.1999\",\"name\":\"Jason Bourne\",\"salary\":123.45678}", Person9.class);
+        assertEquals(p.name, after.name);
+        assertEquals(p.birthDate, after.birthDate);
+        assertEquals(p.salary, after.salary);
+    }
+    
+    public static class Customer {
+        private int id;
+        private String name;
+        private String organization;
+        private String position;
+        
+        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 getOrganization() {
+            return organization;
+        }
+        public void setOrganization(String organization) {
+            this.organization = organization;
+        }
+        public String getPosition() {
+            return position;
+        }
+        public void setPosition(String position) {
+            this.position = position;
+        }
+    }
+
+    public static class CustomerAnnotated {
+        @JsonbProperty("customer_id")
+        private int id;
+
+        @JsonbProperty("customer_name")
+        private String name;
+        
+        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 static class CustomerAdapter implements JsonbAdapter<Customer, CustomerAnnotated> {
+        @Override
+        public CustomerAnnotated adaptToJson(Customer c) throws Exception {
+            CustomerAnnotated customer = new CustomerAnnotated();
+            customer.setId(c.getId());
+            customer.setName(c.getName());
+            return customer;
+        }
+
+        @Override
+        public Customer adaptFromJson(CustomerAnnotated adapted) throws Exception {
+            Customer customer = new Customer();
+            customer.setId(adapted.getId());
+            customer.setName(adapted.getName());
+            return customer;
+        }
+    }
+    
+    @Test
+    public void testAdapters1() {
+        // Create Jsonb with default configuration
+        Jsonb jsonb = JsonbBuilder.create();
+
+        // Create customer
+        Customer customer = new Customer();
+
+        customer.setId(1);
+        customer.setName("Jason Bourne");
+        customer.setOrganization("Super Agents");
+        customer.setPosition("Super Agent");
+
+        // Serialize
+        String json = jsonb.toJson(customer);
+        assertEquals("{\"id\":1,\"name\":\"Jason Bourne\",\"organization\":\"Super Agents\",\"position\":\"Super Agent\"}", json);
+    }
+    
+    @Test
+    public void testAdapters2() {
+     // Create custom configuration
+        JsonbConfig config = new JsonbConfig()
+            .withAdapters(new CustomerAdapter());
+
+        // Create Jsonb with custom configuration
+        Jsonb jsonb = JsonbBuilder.create(config);
+
+        // Create customer
+        Customer customer = new Customer();
+
+        customer.setId(1);
+        customer.setName("Jason Bourne");
+        customer.setOrganization("Super Agents");
+        customer.setPosition("Super Agent");
+
+        // Serialize
+        String json = jsonb.toJson(customer);
+        assertEquals("{\"customer_id\":1,\"customer_name\":\"Jason Bourne\"}", json);
+    }
+    
+    public static class CustomerSerializer implements JsonbSerializer<Customer> {
+        @Override
+        public void serialize(Customer customer, JsonGenerator generator, SerializationContext ctx) {
+            generator.writeStartObject();
+            generator.write("customer_id", customer.getId());
+            generator.write("customer_name", customer.getName());
+            generator.writeEnd();
+        }
+    }
+
+    public static class CustomerDeserializer implements JsonbDeserializer<Customer> {
+        @Override
+        public Customer deserialize(JsonParser parser, DeserializationContext ctx, Type rtType) {
+            Customer customer = new Customer();
+            JsonParser.Event next;
+
+            // Moving parser by hand looking for customer_id and customer_name properties
+            while ((next = parser.next()) != JsonParser.Event.END_OBJECT) {
+                if (next == JsonParser.Event.KEY_NAME) {
+                    String jsonKeyName = parser.getString();
+
+                    // Move to json value
+                    parser.next();
+
+                    if ("customer_id".equals(jsonKeyName)) {
+                        customer.setId(parser.getInt());
+                    } else if ("customer_name".equals(jsonKeyName)) {
+                        customer.setName(parser.getString());
+                    }
+                }
+            }
+            return customer;
+        }
+    }
+    
+    @Test
+    public void testSerializerDeserializer() {
+        // Create pojo
+        Customer customer = new Customer();
+        customer.setId(1);
+        customer.setName("Freddie");
+        customer.setOrganization("Super Agents");
+        customer.setPosition("Super Agent");
+
+        // Also configurable with @JsonbSerializer / JsonbDeserializer on properties and class.
+        JsonbConfig config = new JsonbConfig()
+                .withSerializers(new CustomerSerializer())
+                .withDeserializers(new CustomerDeserializer());
+
+        Jsonb jsonb = JsonbBuilder.create(config);
+        String json = jsonb.toJson(customer);
+        assertEquals("{\"customer_id\":1,\"customer_name\":\"Freddie\"}", json);
+        
+        Customer result = jsonb.fromJson(json, Customer.class);
+        assertEquals(customer.getId(), result.getId());
+        assertEquals(customer.getName(), result.getName());
+        assertNull(result.getOrganization());
+        assertNull(result.getPosition());
+    }
+}