A pitfall in JSON formatting of objects in Java, javajson formatting

Source: Internet
Author: User
Tags tojson

A pitfall in JSON formatting of objects in Java, javajson formatting

A json pitfall is encountered in the project. Record.

Directly run the Code:

import java.util.ArrayList;import com.alibaba.fastjson.JSON;public class MyList<E> extends ArrayList<E> {    private int size;    private String specialName;        public MyList(){        super(0);    }        public MyList(int size){        super(0);        this.size = size;    }    public MyList(String specialName){        super(0);        this.specialName = specialName;    }    public MyList(int size, String specialName){        super(0);        this.size = size;        this.specialName = specialName;    }    public int getSize() {        return size;    }    public void setSize(int size) {        this.size = size;    }    public String getSpecialName() {        return specialName;    }    public void setSpecialName(String specialName) {        this.specialName = specialName;    }    public static void main(String[] args){        MyList<Integer> list = new MyList<Integer>();        list.add(1);        list.add(2);        list.add(3);        list.add(4);        list.setSpecialName("just a test");        list.setSize(4);        System.out.println(JSON.toJSON(list));        System.out.println(JSON.toJSONString(list));    }}

The output result is:

[1,2,3,4][1,2,3,4]

However, the expected result is similar to the following:

{size:4, specialName:"just a test", [1,2,3,4]}

So where is the problem?As a result, the size attribute and specialName of MyList are discarded during JSON formatting.?

The following is an example:

import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import com.alibaba.fastjson.JSON;public class MyList2<E> {    private int size;    private String specialName;    private List<E> list;        public MyList2(){            }    public int getSize() {        return size;    }    public void setSize(int size) {        this.size = size;    }    public String getSpecialName() {        return specialName;    }    public void setSpecialName(String specialName) {        this.specialName = specialName;    }    public List<E> getList() {        return list;    }    public void setList(List<E> list) {        this.list = list;    }        public static void main(String[] args){        MyList2<Integer> myList = new MyList2<Integer>();        ArrayList<Integer> list = new ArrayList<>();        list.add(1);        list.add(2);        list.add(3);        list.add(4);                myList.setSpecialName("just a test");        myList.setSize(4);        myList.setList(list);        System.out.println(JSON.toJSON(myList));        System.out.println(JSON.toJSONString(myList));                System.out.println("----------------");                Map<String, Object> map = new HashMap<>();        map.put("size", 4);        map.put("specialName", "just a test");        map.put("list", list);        map.put("myList", myList);        System.out.println(JSON.toJSON(map));    }}

The output result is:

{"list":[1,2,3,4],"size":4,"specialName":"just a test"}{"list":[1,2,3,4],"size":4,"specialName":"just a test"}----------------{"specialName":"just a test","size":4,"list":[1,2,3,4],"myList":{"list":[1,2,3,4],"size":4,"specialName":"just a test"}}

The result is correct.

Here, we should know why.

The expected result of the first code above:

{Size: 4, specialName: "just a test", [1, 2, 4]}

But think about it. Is there any problem with this format? Think twice.

FK, this format is completely incorrect! It is invalid. Imagine,The JSON format is white. It is a subset of Javascript. A valid json object is an object in javascript.But:

{Size: 4, specialName: "just a test", [1, 2, 4]}

Is it a legal javascript Object ????

Obviously, it is not. Because [1, 2, 3, 4] is inaccessible, it does not correspond to an attribute..So we cannot access it. So it is not a legal javascript object, and it is obviously not a legal json object.. Therefore, in the first example, the output result [1, 2, 3, 4] is actually acceptable.

We wantForcibly convert a Java object not suitable for conversion to JSON format into a json format, so unexpected situations will inevitably occur.. Then how does the result come from [1, 2, 3, 4. After debugging, the reason is,Because MyList inherits from ArrayList, it is processed as a List or array in JSON format., Let's take a look at the relevant source code:

    public static final Object toJSON(Object javaObject) {        return toJSON(javaObject, ParserConfig.getGlobalInstance());    }    @SuppressWarnings("unchecked")    public static final Object toJSON(Object javaObject, ParserConfig mapping) {        if (javaObject == null) {            return null;        }        if (javaObject instanceof JSON) {            return (JSON) javaObject;        }        if (javaObject instanceof Map) {            Map<Object, Object> map = (Map<Object, Object>) javaObject;            JSONObject json = new JSONObject(map.size());            for (Map.Entry<Object, Object> entry : map.entrySet()) {                Object key = entry.getKey();                String jsonKey = TypeUtils.castToString(key);                Object jsonValue = toJSON(entry.getValue());                json.put(jsonKey, jsonValue);            }            return json;        }        if (javaObject instanceof Collection) {            Collection<Object> collection = (Collection<Object>) javaObject;            JSONArray array = new JSONArray(collection.size());            for (Object item : collection) {                Object jsonValue = toJSON(item);                array.add(jsonValue);            }            return array;        }

Our MyList object is treated as JSONArray because it is true at the if (javaObject instanceof Collection,Every time you process an item in JSONArray, the size and specialName attributes are obviously not processed.So these two attributes are discarded. This is the processing process of JSON. toJSON.

Let's take a look at JSON. toJSONString (), which is actually the same. It is processed as an array or a List:

    public ObjectSerializer getObjectWriter(Class<?> clazz) {        ObjectSerializer writer = get(clazz);        if (writer == null) {            try {                final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();                for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {                    if (!(o instanceof AutowiredObjectSerializer)) {                        continue;                    }                    AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;                    for (Type forType : autowired.getAutowiredFor()) {                        put(forType, autowired);                    }                }            } catch (ClassCastException ex) {                // skip            }            writer = get(clazz);        }        if (writer == null) {            final ClassLoader classLoader = JSON.class.getClassLoader();            if (classLoader != Thread.currentThread().getContextClassLoader()) {                try {                    for (Object o : ServiceLoader.load(AutowiredObjectSerializer.class, classLoader)) {                        if (!(o instanceof AutowiredObjectSerializer)) {                            continue;                        }                        AutowiredObjectSerializer autowired = (AutowiredObjectSerializer) o;                        for (Type forType : autowired.getAutowiredFor()) {                            put(forType, autowired);                        }                    }                } catch (ClassCastException ex) {                    // skip                }                writer = get(clazz);            }        }        if (writer == null) {            if (Map.class.isAssignableFrom(clazz)) {                put(clazz, MapSerializer.instance);            } else if (List.class.isAssignableFrom(clazz)) {                put(clazz, ListSerializer.instance);

The above codeElse if (List. class. isAssignableFrom (clazz) is true, so ListSerializer. instance is used to process the objects in MyList.That is, it is processed as a java. util. List, so the size and specialName attributes are naturally discarded. The principle is the same as above.

Summary:

1) if MyList inherits objects from the List and has extended attributes, it cannot be properly represented in json format and will be processed as a List, to discard other non-List attributes.

2)The alternative method is to use combination instead of inheritance, or use Map. java. util. Map is naturally the most suitable for json format.In fact, the object in javascript is actually a Map to some extent. The attribute name is the key in map, and the attribute value is the value of map.

3) JSON format introduction see: http://www.cnblogs.com/digdeep/p/4572662.html

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.