Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin data class convert with gson...And the default value was convert by zero or null

I use GSON to convert data class which the server comeback. and i define the data class like this... And theres some field i don't want to convert with GSON.. So i add the ExclusionStrategy with Annotation. Through the test, i found that AnnotationExclusionStrategy operating normally,And skip the field i don't want to convert. I add annotation with the field like uiType and testData,But actually when I print the Object out. I found the field uiType and testData had convert to zero and null..

Then i create a new data class. the uiType and testData had not erase to zero or null.Is go wrong when GSON convert??

if there's any way to solve this problem?

Here's the code.

Data class entity:

data class Product(@SerializedName("num_iid") var productId: Long,
               @SerializedName("title") var productName: String,
               @SerializedName("item_url") var productUrl: String,
               @SerializedName("pict_url") var productPic: String,
               @SerializedName("small_images") var productPics: ProductImageList,
               @SerializedName("zk_final_price") var productPrice: String,
               @SerializedName("reserve_price") var originPrice: String,
               @SerializedName("provcity") var place: String,
               @SerializedName("volume") var sellCount: String,
               @SerializedName("user_type") var sellerType: String,
               @SerializedName("nick") var sellerName: String,
               @SerializedName("seller_id") var sellerId: Long
) : MultiItemEntity {

@Exclude
@ShoppingCenterConstant.ProductListUiType
var uiType = ShoppingCenterConstant.LIST_UI_TYPE_COMMON

var testData = "TestData"

override fun getItemType(): Int {
    return ShoppingCenterConstant.LIST_UI_TYPE_COMMON
}

override fun toString(): String {
    return "Product(productId=$productId, productName='$productName', productUrl='$productUrl', productPic='$productPic', productPics=$productPics, productPrice='$productPrice', originPrice='$originPrice', place='$place', sellCount='$sellCount', sellerType='$sellerType', sellerName='$sellerName', sellerId=$sellerId, uiType=$uiType, testData='$testData')"
}
}

GSON AnnotationExclusion:

public class AnnotationExclusion implements ExclusionStrategy {

public static final String TAG = GsonUtil.TAG;

@Override
public boolean shouldSkipField(FieldAttributes f) {
    boolean isShouldSkip = f.getAnnotation(Exclude.class) != null;
    return isShouldSkip;
}

@Override
public boolean shouldSkipClass(Class<?> clazz) {
    boolean isShouldSkip = clazz.getAnnotation(Exclude.class) != null;
    return isShouldSkip;
}

}

The place i printout:

override fun showData(data: BaseListBean<Product>) {
    var product = Product(0, "", "", ""
            , ProductImageList(List(0, { String() })), "", "", "", ""
            , "", "", 0)
    LogUtils.info("print out new product:" + product)
    mResultListener.onResponse(data)
}

Result with GSON Converter, and you can see the field uiType and testData had convert to zero or null:

Product(productId=552634381786, productName='eoodoo新生儿礼盒婴儿衣服秋冬套装出生满月礼物初生母婴宝宝用品', productUrl='http://item.taobao.com/item.htm?id=552634381786', productPic='https://img.alicdn.com/tfscom/i4/2832303009/O1CN013tXM6L1Y6AFHSy7xN_!!0-item_pic.jpg', productPics=com.laka.ergou.mvp.shopping.center.model.bean.ProductImageList@1033f68, productPrice='259.72', originPrice='755.00', place='浙江 杭州', sellCount='1159', sellerType='1', sellerName='eoodoo旗舰店', sellerId=2832303009, uiType=0, testData='null')

Result with create new Object , this seem fine:

Product(productId=0, productName='', productUrl='', productPic='', productPics=com.laka.ergou.mvp.shopping.center.model.bean.ProductImageList@1c228b, productPrice='', originPrice='', place='', sellCount='', sellerType='', sellerName='', sellerId=0, uiType=1, testData='testData')

Here is the JSON i used .But the field like uiType and testData. just the field i define in the code and used in local, these are not the server comeback json field

{
"tbk_item_get_response":{
    "results":{
        "n_tbk_item":[
            {
                "item_url":"http://item.taobao.com/item.htm?id=582889134126",
                "nick":"宝绒羊服饰旗舰店",
                "num_iid":582889134126,
                "pict_url":"https://img.alicdn.com/tfscom/i1/1720028843/O1CN01ERqlHz2FC8tL1m2tz_!!0-item_pic.jpg",
                "provcity":"浙江 杭州",
                "reserve_price":"1318.00",
                "seller_id":1720028843,
                "small_images":{
                    "string":[
                        "https://img.alicdn.com/tfscom/i4/1720028843/O1CN01xD9JyD2FC8tJMRuk2_!!1720028843.jpg",
                        "https://img.alicdn.com/tfscom/i4/1720028843/O1CN01twbf3O2FC8tLEHVJc_!!1720028843.jpg",
                        "https://img.alicdn.com/tfscom/i4/1720028843/O1CN01zM2clN2FC8tE0LO5q_!!1720028843.jpg",
                        "https://img.alicdn.com/tfscom/i3/1720028843/O1CN01WW6xzz2FC8tKjoitz_!!1720028843.jpg"
                    ]
                },
                "title":"羽绒服女2018新款女装冬季短款韩版时尚银色亮面滩羊毛领加厚外套",
                "user_type":1,
                "volume":2138,
                "zk_final_price":"498.00"
            }
        ]
    },
    "total_results":19643,
    "request_id":"kvbqd1jrgqcg"
}

}

like image 754
Rayman Avatar asked Dec 26 '18 08:12

Rayman


People also ask

Does GSON work with Kotlin?

Google Gson is one of the most popular libraries for handling JSON objects, and many popular programming languages support it, including Kotlin. In this tutorial, we'll explore how to serialize and deserialize JSON arrays with Kotlin using Gson.

Can we make data class open in Kotlin?

Data classes cannot be abstract, open, sealed, or inner.


1 Answers

Gson is currently breaking Kotlin type-safety. It can write null to non-null property. That can happen when json that you reading have that field assigned to null. For example if you have data class:

data class A (
    var nonNullable: String = "",
    var other: Int = 42
)

And following JSON:

{
    "nonNullable": null,
    "other": 91
}

You will have null in nonNullable as result.

To avoid that you can create custom GSON type converter for your class or make nonNullable actually nullable, but provide getter and setter, that will ignore null value:

class A {
    var nonNullable: String? = ""
        get() = field ?: ""
        set(value) {
            if (value != null) {
                field = value
            }
        }
}

And same thing with 0 - that means that JSON that you parsing have that field assigned to zero. Or, if that not so - provide us your JSON to make question more clear.

like image 196
Andrei Vinogradov Avatar answered Dec 03 '22 23:12

Andrei Vinogradov