網頁

2019/4/30

Java 多型物件轉JSON字串時,子類別的成員屬性是否會輸出?

如果你有一個變數型態為父類別Parent,但實例是子類別Child的多型物件(Polymorphism),則將該物件用Gson或Jaskson Databind含式庫是轉成JSON字串時,子類別中的屬性是否也會輸出呢?

請見以下實驗結果,若多型物件子類別的屬性與父類別有相同的屬性名稱時使用Gson轉JSON字串時會出現錯誤。例如下面父類Parent及子類Child都有相同的屬性名稱name,則出現錯誤
java.lang.IllegalArgumentException: [Class] declares multiple JSON fields named [name]

import com.google.gson.Gson;

public class Main {

    public static void main(String[] args) throws Exception {

        Parent person = new Child();
        
        Gson gson = new Gson();
        System.out.println(gson.toJson(person)); // IllegalArgumentException錯誤

    }

}

class Parent {

    String name = "David";

    //省略getter setter
}

class Child extends Parent {

    String name = "Alex";

    //省略getter setter
}

但用Jaskon DataBind仍可以正常的輸出子類別的屬性的JSON字串。

import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {

    public static void main(String[] args) throws Exception {

        Parent person = new Child();
        
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(person)); // {"name":"Alex"}

    }

}

class Parent {

    String name = "David";

    //省略getter setter
}

class Child extends Parent {

    String name = "Alex";

    //省略getter setter
}

如果屬性名稱沒有重複,則Gson和Jaskson Databind兩者則可正常印出父類及子類屬性的JSON字串。

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;

public class Main {

    public static void main(String[] args) throws Exception {

        Parent person = new Child();

        Gson gson = new Gson();
        System.out.println(gson.toJson(person)); // {"bike":"HONDA NM4-02","car":"BENZ C300"}

        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(person)); // {"car":"BENZ C300","bike":"HONDA NM4-02"}

    }

}

class Parent {

    String car = "BENZ C300";

    //省略getter setter
}

class Child extends Parent {

    String bike = "HONDA NM4-02";

    //省略getter setter
}

最後要注意的是,Jaskson Databind轉成JSON字串的物件必須要有getter setter,否則會出現錯誤:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class [Class] and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)


參考:

沒有留言:

張貼留言