org.springside.examples.showcase.demos.utilities.json.JsonDemo.java Source code

Java tutorial

Introduction

Here is the source code for org.springside.examples.showcase.demos.utilities.json.JsonDemo.java

Source

/*******************************************************************************
 * Copyright (c) 2005, 2014 springside.github.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 *******************************************************************************/
package org.springside.examples.showcase.demos.utilities.json;

import static org.assertj.core.api.Assertions.*;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.junit.Test;
import org.springside.modules.mapper.JsonMapper;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.introspect.AnnotatedMethod;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * Jackson???Feature.
 * 
 * @author calvin
 */
public class JsonDemo {

    private static JsonMapper mapper = JsonMapper.nonDefaultMapper();

    // // ?  ////

    /**
     * ?/?Json.
     */
    @Test
    public void toJson() throws Exception {
        // Bean
        TestBean bean = new TestBean("A");
        String beanString = mapper.toJson(bean);
        System.out.println("Bean:" + beanString);
        assertThat(beanString).isEqualTo("{\"name\":\"A\"}");

        // Map
        Map<String, Object> map = Maps.newLinkedHashMap();
        map.put("name", "A");
        map.put("age", 2);
        String mapString = mapper.toJson(map);
        System.out.println("Map:" + mapString);
        assertThat(mapString).isEqualTo("{\"name\":\"A\",\"age\":2}");

        // List<String>
        List<String> stringList = Lists.newArrayList("A", "B", "C");
        String listString = mapper.toJson(stringList);
        System.out.println("String List:" + listString);
        assertThat(listString).isEqualTo("[\"A\",\"B\",\"C\"]");

        // List<Bean>
        List<TestBean> beanList = Lists.newArrayList(new TestBean("A"), new TestBean("B"));
        String beanListString = mapper.toJson(beanList);
        System.out.println("Bean List:" + beanListString);
        assertThat(beanListString).isEqualTo("[{\"name\":\"A\"},{\"name\":\"B\"}]");

        // Bean[]
        TestBean[] beanArray = new TestBean[] { new TestBean("A"), new TestBean("B") };
        String beanArrayString = mapper.toJson(beanArray);
        System.out.println("Array List:" + beanArrayString);
        assertThat(beanArrayString).isEqualTo("[{\"name\":\"A\"},{\"name\":\"B\"}]");
    }

    /**
     * Json???/?.
     */
    @Test
    public void fromJson() throws Exception {
        // Bean
        String beanString = "{\"name\":\"A\"}";
        TestBean bean = mapper.fromJson(beanString, TestBean.class);
        System.out.println("Bean:" + bean);

        // Map
        String mapString = "{\"name\":\"A\",\"age\":2}";
        Map<String, Object> map = mapper.fromJson(mapString, HashMap.class);
        System.out.println("Map:");
        for (Entry<String, Object> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " " + entry.getValue());
        }

        // List<String>
        String listString = "[\"A\",\"B\",\"C\"]";
        List<String> stringList = mapper.fromJson(listString, List.class);
        System.out.println("String List:");
        for (String element : stringList) {
            System.out.println(element);
        }

        // List<Bean>
        String beanListString = "[{\"name\":\"A\"},{\"name\":\"B\"}]";
        JavaType beanListType = mapper.contructCollectionType(List.class, TestBean.class);
        List<TestBean> beanList = mapper.fromJson(beanListString, beanListType);
        System.out.println("Bean List:");
        for (TestBean element : beanList) {
            System.out.println(element);
        }
    }

    /**
     * ???Inclusion.
     */
    @Test
    public void threeTypeInclusion() {
        TestBean bean = new TestBean("A");

        // ?
        JsonMapper normalMapper = new JsonMapper();
        assertThat(normalMapper.toJson(bean))
                .isEqualTo("{\"name\":\"A\",\"defaultValue\":\"hello\",\"nullValue\":null}");

        // ??nullValue
        JsonMapper nonEmptyMapper = JsonMapper.nonEmptyMapper();
        assertThat(nonEmptyMapper.toJson(bean)).isEqualTo("{\"name\":\"A\",\"defaultValue\":\"hello\"}");

        // ???nullValuedefaultValue
        JsonMapper nonDefaultMaper = JsonMapper.nonDefaultMapper();
        assertThat(nonDefaultMaper.toJson(bean)).isEqualTo("{\"name\":\"A\"}");
    }

    /*
     * JaxbannotaionproperNameignorepropertyOrder
     */
    @Test
    public void jacksonAnnoation() {
        TestBean2 testBean = new TestBean2(1, "foo", 18);
        // name???productNameageignore
        assertThat(mapper.toJson(testBean)).isEqualTo("{\"productName\":\"foo\",\"id\":1}");
    }

    /*
     * Jaxbannotaion
     */
    @Test
    public void jaxbAnnoation() {
        JsonMapper newMapper = new JsonMapper();
        newMapper.enableJaxbAnnotation();
        TestBean3 testBean = new TestBean3(1, "foo", 18);
        // name???productNameageignore
        assertThat(newMapper.toJson(testBean)).isEqualTo("{\"productName\":\"foo\",\"id\":1}");
    }

    // ?
    @JsonPropertyOrder({ "name", "id" })
    public static class TestBean2 {

        public long id;

        @JsonProperty("productName")
        public String name;

        @JsonIgnore
        public int age;

        public TestBean2() {

        }

        public TestBean2(long id, String name, int age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }

    }

    // ?
    @XmlType(propOrder = { "name", "id" })
    public static class TestBean3 {

        public long id;

        @XmlElement(name = "productName")
        public String name;

        @XmlTransient
        public int age;

        public TestBean3() {

        }

        public TestBean3(long id, String name, int age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }

    }

    /**
     * BeanJSON??Bean?.
     */
    @Test
    public void updateBean() {
        String jsonString = "{\"name\":\"A\"}";

        TestBean bean = new TestBean();
        bean.setDefaultValue("Foobar");

        mapper.update(jsonString, bean);

        // name
        assertThat(bean.getName()).isEqualTo("A");
        // DefaultValue?Json??
        assertThat(bean.getDefaultValue()).isEqualTo("Foobar");
    }

    /**
     * jsonp?.
     */
    @Test
    public void jsonp() {
        TestBean bean = new TestBean("foo");
        assertThat(mapper.toJsonP("callback", bean)).isEqualTo("callback({\"name\":\"foo\"})");
    }

    /**
     * Bean, ???Mapper?Null???.
     */
    public static class TestBean {

        private String name;
        private String defaultValue = "hello"; // ???
        private String nullValue = null; // ????

        public TestBean() {
        }

        public TestBean(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

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

        public String getDefaultValue() {
            return defaultValue;
        }

        public void setDefaultValue(String defaultValue) {
            this.defaultValue = defaultValue;
        }

        public String getNullValue() {
            return nullValue;
        }

        public void setNullValue(String nullValue) {
            this.nullValue = nullValue;
        }

        @Override
        public String toString() {
            return "TestBean [defaultValue=" + defaultValue + ", name=" + name + ", nullValue=" + nullValue + "]";
        }
    }

    // //?////

    /**
     * ?.
     */
    @Test
    public void enumType() {
        // toJSon?enum.name()
        assertThat(mapper.toJson(TestEnum.One)).isEqualTo("\"One\"");
        // fromJsonenum.name()enum.order()
        assertThat(mapper.fromJson("\"One\"", TestEnum.class)).isEqualTo(TestEnum.One);
        assertThat(mapper.fromJson("0", TestEnum.class)).isEqualTo(TestEnum.One);

        // enum.toString(), ???.
        // toString()indexenum.name()enum.order()?????
        JsonMapper newMapper = new JsonMapper();
        newMapper.enableEnumUseToString();
        assertThat(newMapper.toJson(TestEnum.One)).isEqualTo("\"1\"");
        assertThat(newMapper.fromJson("\"1\"", TestEnum.class)).isEqualTo(TestEnum.One);
    }

    /**
     * Bean.
     */
    public static enum TestEnum {
        One(1), Two(2), Three(3);

        private final int index;

        TestEnum(int index) {
            this.index = index;
        }

        @Override
        public String toString() {
            return String.valueOf(index);
        }
    }

    /**
     * ?,Timestamp??2.0??@JsonFormat?.
     * JodaTime???Timestamp?, JodaTime.toString().
     */
    @Test
    public void dateType() {

        mapper.getMapper().registerModule(new JodaModule());

        Date date = new Date();
        DateTime dateTime = new DateTime(date);
        String timestampString = String.valueOf(date.getTime());
        String format = "yyyy-MM-dd HH:mm:ss";
        String formatedString = new DateTime(date).toString(format);

        DateBean dateBean = new DateBean();
        dateBean.startDate = date;
        dateBean.endDate = date;
        dateBean.dateTime = dateTime;

        // to json
        String expectedJson = "{\"startDate\":" + timestampString + ",\"endDate\":\"" + formatedString
                + "\",\"dateTime\":" + timestampString + "}";
        assertThat(mapper.toJson(dateBean)).isEqualTo(expectedJson);

        // from json
        Date expectedEndDate = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").parseDateTime(formatedString)
                .toDate();

        DateBean resultBean = mapper.fromJson(expectedJson, DateBean.class);
        assertThat(resultBean.startDate).isEqualTo(date);
        assertThat(resultBean.endDate).isEqualTo(expectedEndDate);
    }

    public static class DateBean {
        // timestamp
        public Date startDate;
        // annotation?
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+08:00")
        public Date endDate;

        public DateTime dateTime;
    }

    /**
     * ,,Empty?,"null".
     */
    @Test
    public void nullAndEmpty() {
        // toJson //

        // Null Bean
        TestBean nullBean = null;
        String nullBeanString = mapper.toJson(nullBean);
        assertThat(nullBeanString).isEqualTo("null");

        // Empty List
        List<String> emptyList = Lists.newArrayList();
        String emptyListString = mapper.toJson(emptyList);
        assertThat(emptyListString).isEqualTo("[]");

        // fromJson //

        // Null String for Bean
        TestBean nullBeanResult = mapper.fromJson(null, TestBean.class);
        assertThat(nullBeanResult).isNull();

        nullBeanResult = mapper.fromJson("null", TestBean.class);
        assertThat(nullBeanResult).isNull();

        // Null/Empty String for List
        List nullListResult = mapper.fromJson(null, List.class);
        assertThat(nullListResult).isNull();

        nullListResult = mapper.fromJson("null", List.class);
        assertThat(nullListResult).isNull();

        nullListResult = mapper.fromJson("[]", List.class);
        assertThat(nullListResult).isEmpty();
    }

    // //  ////
    /**
     * ?POJO.
     */
    @Test
    public void cycleReferenceBean() {
        // ?parentchildren? child1,child2, child1/child2parent??parent.
        CycleReferenceBean parent = new CycleReferenceBean("parent");

        CycleReferenceBean child1 = new CycleReferenceBean("child1");
        child1.setParent(parent);
        parent.getChildren().add(child1);

        CycleReferenceBean child2 = new CycleReferenceBean("child2");
        child2.setParent(parent);
        parent.getChildren().add(child2);

        // ?, jsonchildrenchild1/child2??parent
        String jsonString = "{\"name\":\"parent\",\"children\":[{\"name\":\"child1\"},{\"name\":\"child2\"}]}";
        assertThat(mapper.toJson(parent)).isEqualTo(jsonString);

        // ???child1??parent?
        assertThat(mapper.toJson(child1)).isEqualTo("{\"name\":\"child1\"}");

        // ????Json?parentchild1/child2.
        CycleReferenceBean parentResult = mapper.fromJson(jsonString, CycleReferenceBean.class);
        assertThat(parentResult.getChildren().get(0).getParent().getName()).isEqualTo("parent");

        // ????child1parent
        CycleReferenceBean child1Result = mapper.fromJson("{\"name\":\"child1\"}", CycleReferenceBean.class);
        assertThat(child1Result.parent).isNull();
        assertThat(child1Result.getName()).isEqualTo("child1");
    }

    /**
     * ?POJOBean,@JsonBackReference  @JsonManagedReference .
     */
    public static class CycleReferenceBean {

        private String name;
        private CycleReferenceBean parent;
        private List<CycleReferenceBean> children = Lists.newArrayList();

        public CycleReferenceBean() {
        }

        public CycleReferenceBean(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

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

        // ?gettersetter?annotation
        @JsonBackReference
        public CycleReferenceBean getParent() {
            return parent;
        }

        @JsonBackReference
        public void setParent(CycleReferenceBean parent) {
            this.parent = parent;
        }

        @JsonManagedReference
        public List<CycleReferenceBean> getChildren() {
            return children;
        }

        @JsonManagedReference
        public void setChildren(List<CycleReferenceBean> children) {
            this.children = children;
        }
    }

    /**
     * ?Bean.
     * ?Bean?Map<String,object>
     * ???
     * Jackson???Map??@JsonAnyGetter/SetterMap?
     */
    @Test
    public void extensibleBean() {
        // ??MapJSON.
        String jsonString = "{\"name\" : \"Foobar\",\"age\" : 37,\"occupation\" : \"coder man\"}";
        ExtensibleBean extensibleBean = mapper.fromJson(jsonString, ExtensibleBean.class);
        // 
        assertThat(extensibleBean.getName()).isEqualTo("Foobar");
        assertThat(extensibleBean.getProperties().get("name")).isNull();

        // ?
        assertThat(extensibleBean.getProperties().get("occupation")).isEqualTo("coder man");
    }

    /**
     * ?Bean.@JsonAnySetter@JsonAnyGetter.
     */
    public static class ExtensibleBean {
        // 
        private String name;
        // 
        private final Map<String, String> properties = Maps.newHashMap();

        public ExtensibleBean() {
        }

        @JsonAnySetter
        public void add(String key, String value) {
            properties.put(key, value);
        }

        @JsonAnyGetter
        public Map<String, String> getProperties() {
            return properties;
        }

        public String getName() {
            return name;
        }

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

    /**
     * ??POJO???????Jackson?View?.
     */
    @Test
    public void multiViewBean() throws IOException {
        MultiViewBean multiViewBean = new MultiViewBean();
        multiViewBean.setName("Foo");
        multiViewBean.setAge(16);
        multiViewBean.setOtherValue("others");

        // public view
        ObjectWriter publicWriter = mapper.getMapper().writerWithView(Views.Public.class);
        assertThat(publicWriter.writeValueAsString(multiViewBean))
                .isEqualTo("{\"name\":\"Foo\",\"otherValue\":\"others\"}");

        // internal view
        ObjectWriter internalWriter = mapper.getMapper().writerWithView(Views.Internal.class);
        assertThat(internalWriter.writeValueAsString(multiViewBean))
                .isEqualTo("{\"age\":16,\"otherValue\":\"others\"}");

    }

    public static class Views {
        static class Public {
        }

        static class Internal {
        }
    }

    /**
     * ???View??Bean.
     */
    public static class MultiViewBean {
        private String name;
        private int age;
        private String otherValue;

        @JsonView(Views.Public.class)
        public String getName() {
            return name;
        }

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

        @JsonView(Views.Internal.class)
        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public String getOtherValue() {
            return otherValue;
        }

        public void setOtherValue(String otherValue) {
            this.otherValue = otherValue;
        }
    }

    // //////

    /**
     * ????MoneyLong.
     */
    @Test
    public void customConverter() {

        JsonMapper newMapper = JsonMapper.nonEmptyMapper();

        SimpleModule moneyModule = new SimpleModule("MoneyModule");
        moneyModule.addSerializer(new MoneySerializer());
        moneyModule.addDeserializer(Money.class, new MoneyDeserializer());
        newMapper.getMapper().registerModule(moneyModule);

        // tojson
        User user = new User();
        user.setName("foo");
        user.setSalary(new Money(1.2));

        String jsonString = newMapper.toJson(user);

        assertThat(jsonString).isEqualTo("{\"name\":\"foo\",\"salary\":\"1.2\"}");

        // from
        User resultUser = newMapper.fromJson(jsonString, User.class);
        assertThat(resultUser.getSalary().value).isEqualTo(1.2);

    }

    public class MoneySerializer extends StdSerializer<Money> {
        public MoneySerializer() {
            super(Money.class);
        }

        @Override
        public void serialize(Money value, JsonGenerator jgen, SerializerProvider provider) throws IOException {

            jgen.writeString(value.toString());
        }
    }

    public class MoneyDeserializer extends StdDeserializer<Money> {
        public MoneyDeserializer() {
            super(Money.class);
        }

        @Override
        public Money deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
            return Money.valueOf(jp.getText());
        }

    }

    public static class Money {
        private final Double value;

        public Money(Double value) {
            this.value = value;
        }

        public static Money valueOf(String value) {
            Double srcValue = Double.valueOf(value);
            return new Money(srcValue);
        }

        @Override
        public String toString() {
            return value.toString();
        }
    }

    /**
     * ?Money.
     */
    public static class User {
        private String name;
        private Money salary;

        public String getName() {
            return name;
        }

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

        public Money getSalary() {
            return salary;
        }

        public void setSalary(Money salary) {
            this.salary = salary;
        }

    }

    /**
     *  ??
     */
    @Test
    public void customPropertyNaming() throws JsonMappingException {

        TestBean bean = new TestBean("foo");
        bean.setDefaultValue("bar");
        JsonMapper newMapper = JsonMapper.nonEmptyMapper();
        newMapper.getMapper().setPropertyNamingStrategy(new LowerCaseNaming());
        assertThat(newMapper.toJson(bean)).isEqualTo("{\"name\":\"foo\",\"defaultvalue\":\"bar\"}");
    }

    public static class LowerCaseNaming extends PropertyNamingStrategy {
        @Override
        public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
            return defaultName.toLowerCase();
        }
    }
}