【问题标题】:Why is the json string null when I pass a inner object to Gson().toJson(object) in Kotlin?当我将内部对象传递给 Kotlin 中的 Gson().toJson(object) 时,为什么 json 字符串为空?
【发布时间】:2017-11-17 02:41:20
【问题描述】:

我在 Kotlin 中使用 Gson 将对象转换为 json 字符串。

var json2可以返回正确的结果,但是var json1返回null,为什么?

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import bll.SettingManage
import info.dodata.mirror.R
import model.MSetting
import com.google.gson.Gson
import utility.PreferenceTool

class UIMain : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.layout_main)

        data class WiFiDefA(val Name:String, val Status: String)

        var  aWiFiDefA=WiFiDefA("a","b")
        var  json1=Gson().toJson(aWiFiDefA)

        var aWiFiDefB=WiFiDefB("c","d")
        var json2=Gson().toJson(aWiFiDefB)   

    }

    data class WiFiDefB(val Name:String, val Status: String)

}

【问题讨论】:

  • onCreate 方法之外编写您的WiFiDefA 代码。
  • 谢谢,为什么我需要在 onCreate 方法之外编写 WiFiDefA 代码?

标签: android kotlin gson


【解决方案1】:

您观察到的是 Gson 的一个已知限制:它不会序列化匿名或本地类。这就是为什么 Gson 代码明确拒绝序列化您的类 WiFiDefA,在方法 onCreate 中定义(这是 @SangeetSuresh 通过调试 Gson 代码观察到的)。

正如您在 https://github.com/google/gson/issues/298 中看到的那样,提出了一个问题来改变这一点并允许匿名和本地类的序列化,但该问题在一年多前就在没有明确原因的情况下关闭了。

【讨论】:

    【解决方案2】:

    我浏览了 Gson 库,发现下面的代码

    if (isAnonymousOrLocal(clazz)) {
          return true;
        }
    

    isAnonymousOrLocal(clazz)WiFiDefA 返回 true 并且在该方法内部 clazz.isLocalClass() 返回 true

    但是对于 WiFiDefB,这些函数返回 false。

    欲了解更多信息,请访问以下链接

    https://github.com/google/gson/blob/0636635cbffa08157bdbd558b1212e4d806474eb/gson/src/main/java/com/google/gson/internal/Excluder.java

    【讨论】:

    • 谢谢,你的意思是可以在函数中定义类吗?
    • 只有Gson在函数中定义类时可能会出错?
    • @HelloCW 如果您在函数内部定义类,那么它将成为该函数的本地类。因此范围将仅限于该功能。您只能在该函数中访问类。 Gson 对泛型的回复。它将从他们的功能访问类。由于它不可访问,它给出了错误。
    【解决方案3】:

    正如我尝试使用 GSON lib 一样,我已经在 onCreate() 方法之外声明了这两个类。

    如下:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    
        val  aWiFiDefA=WiFiDefA("a","b")
        val json1=Gson().toJson(aWiFiDefA)
    
        Log.d("json1",json1.toString())
        var aWiFiDefB=WiFiDefB("c","d")
        var json2= Gson().toJson(aWiFiDefB)
        Log.d("json2",json2.toString())
    }
    data class WiFiDefA(val Name:String, val Status: String)
    data class WiFiDefB(val Name:String, val Status: String)
    

    这给了我你需要的输出。 输出:

    11-17 11:58:50.448 27978-27978/? D/json1: {"Name":"a","Status":"b"}
    11-17 11:58:50.452 27978-27978/? D/json2: {"Name":"c","Status":"d"}
    

    但是当我尝试你的代码得到如下输出时:

    11-17 11:58:01.312 27584-27584/? D/json1: null
    11-17 11:58:01.320 27584-27584/? D/json2: {"Name":"c","Status":"d"}
    

    我们不能在方法范围内创建类。您可以根据需要创建Nested and Inner Classes 一个类作为嵌套类。

    https://kotlinlang.org/docs/reference/nested-classes.html#nested-and-inner-classes

    【讨论】:

    • 谢谢!是否意味着当我在方法范围内创建类时会导致问题?但是代码可以编译!那么为什么我不能在方法范围内创建一个类呢?
    • 对我有什么想法吗?
    • AFAIK,是否意味着在方法范围内创建类时会导致问题? 是的 。因为 kotlin 只能建议 normalnestedinner 方式类,正如我在答案中添加的那样。如果有任何其他解决方案,肯定会让你知道。谢谢?
    • 谢谢,我的问题是为什么可以在函数中定义类,但会导致错误结果!
    猜你喜欢
    • 2021-11-03
    • 1970-01-01
    • 2018-05-29
    • 1970-01-01
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多