【问题标题】:How to force Kotlin using gson.fromJson() to call my class initializer?如何使用 gson.fromJson() 强制 Kotlin 调用我的类初始化程序?
【发布时间】:2019-02-16 19:58:04
【问题描述】:

在一个 Kotlin 项目中,我让 Gson 将来自 JSON 源的数据注入到我创建的一些类中。数据注入,但类 init{...} 从未被调用。

import com.google.gson.GsonBuilder

fun main(args: Array<String>) {
    val myClass1 = MyClass("Hello!")
    // should have printed "Hello!"

    val jsonOfMyClass = "{myData:\"Hey!\"}"
    val gson = GsonBuilder().create()
    val myClass2 = gson.fromJson(jsonOfMyClass, MyClass::class.java)
    // should have printed "Hey!" but it doesn't init?

    myClass2.printData()
    // so I have to manually call my own init
}

class MyClass constructor(private val myData: String) {
    init {
        printData()
    }

    fun printData() {
        println("My Data: $myData")
    }
}

无需手动调用的结果:

<!-- language: lang-none -->

My Data: Hello!

手动调用的结果:

<!-- language: lang-none -->

My Data: Hello!
My Data: Hey!

不应该这样称呼吗?它正在实例化我的类,对吧?

如果没有,有没有办法强制 init{...}?还是我必须调用公共方法(就像我在示例中所做的那样?)

【问题讨论】:

  • Gson 不调用构造函数。如果您需要该行为,请实现自定义 JsonDeserializer。

标签: java kotlin initialization gson


【解决方案1】:

您可以使用InstanceCreator 来实现。我的示例是用 Java 编写的(为了展示可能性,用了一点不同的情况),但我猜你可以将相关信息选择到你的 Kotlin 项目中。

假设你有这样一个类:

@Getter
public class MyClass {

    private String name; 
    private String myData; 

    public void init(String myData) {
        this.myData = myData;
    }        

}

那么你会有 test.json 像:

{
    "name": "My Name",
    "myData": "My Data"
}

要将 myData 反序列化为其他值或在反序列化阶段进行任何其他初始化,您可以注册 InstanceCreator,如下所示:

public class MyInstanceCreator implements InstanceCreator<MyClass>{

    @Override
    public MyClass createInstance(Type type) {
        MyClass myClass = new MyClass();
        myClass.init("Instance creator put this data");
        return myClass;
    }

}

反序列化:

@Test
public void test() {
    Gson gson = new GsonBuilder().setPrettyPrinting()
        .registerTypeAdapter(MyClass.class, new MyInstanceCreator())
        .create();        
    MyClass myClass = gson.fromJson(
        new InputStreamReader(getClass()
            .getResourceAsStream("test.json")),
        MyClass.class);
   log.info("\n{}", gson.toJson(myClass)); 
}

会产生像这样的对象:

{
  "name": "My Name",
  "createdBy": "Instance creator put this data"
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 2018-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-29
    相关资源
    最近更新 更多