fastJson 格式化繼承自ArrayList 的類時屬性是不會json化的

在項目中遇到了一個JSON的坑。記錄下。javascript

直接上代碼:html

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

輸出的結果爲:java

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

可是咱們指望的結果倒是相似於下面這樣的結果:json

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

那麼是哪裏出問題了呢?致使 MyList的 size 屬性和 specialName 在JSON格式化時,被丟棄了呢數組

下面在看一個例子:app

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

輸出的結果爲:this

{"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,"spe...

結果徹底正確。調試

到這裏,咱們應該能夠知道什麼緣由了。code

上面第一段代碼咱們指望的結果:htm

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

可是想想,這個格式有什麼問題嗎?仔細想想

FK,這個格式是徹底錯誤的!他是不合法的。試想一下,JSON格式說白了,它是 Javascript 的一個子集,合法的json對象它是 javascript 中的對象,可是:

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

他是一個合法的javascript對象嗎????

顯然,它不是的。由於其中的 [1,2,3,4] ,咱們沒法訪問,它沒有對應到一個屬性因此咱們沒法訪問它。因此他不是一個合法的javascript對象,顯然也就更加不是一個合法的json對象了。因此第一個例子,輸出的結果:[1,2,3,4] 實際上是能夠接受的。

是咱們本身想要將一個不適合轉化成JSON格式的Java對象強制轉化成一個json格式,因此也就不免出現意料以外的狀況了。那麼 [1,2,3,4] 這個結果是如何來的呢。通過調試,其中的緣由是,由於MyList繼承自ArrayList,因此在JSON格式化時,就是將其做爲了一個List或者說數組來處理的,咱們看下相關源碼:

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

咱們的MyList的對象,在 if (javaObject instanceof Collection) 處爲true,因此被當作了JSONArray 來處理的,每次處理JSONArray 中的一項,因此顯然就不會處理到 size屬性和specialName屬性了,因此這兩個屬性被拋棄了。這是 JSON.toJSON() 的處理過程。

下面看下 JSON.toJSONString(),其實也是同樣,當成了數組或者說List來處理了:

上面的代碼 else if (List.class.isAssignableFrom(clazz)) 處爲 true,因此實際上是使用了 ListSerializer.instance 來處理了 MyList 的對象的,也就是當作了java.util.List 來處理的,因此天然就拋棄了 size屬性和specialName屬性。和上面的原理是同樣的。

總結下

1)MyList這樣繼承自List的對象,而且有擴展屬性的,它在json格式中是不能十分恰當的表示的,它會被當成List來處理,從而拋棄其它非List的屬性。

2)避免方法就是使用組合代替繼承,或者使用Map,java.util.Map 天生就和json格式是最合適的,其實javascript中的對象,其實在某種程度上就是一個Map而已,屬性名就是map中的key, 屬性的值就是map的value。

3)JSON格式介紹參見:http://www.cnblogs.com/digdeep/p/4572662.html

 

轉載自:http://www.bkjia.com/Javabc/1020836.html

相關文章
相關標籤/搜索