How to force Kotlin using gson.fromJson() to call my class initializer?

问题: In a Kotlin project I have Gson injecting data from a JSON source into some classes I made. The data injects, however the class init{...} is never called. import com.goog...

问题:

In a Kotlin project I have Gson injecting data from a JSON source into some classes I made. The data injects, however the class init{...} is never called.

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

Result without a manual call:

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

My Data: Hello!

Result with a manual call:

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

My Data: Hello!
My Data: Hey!

Should this not be called? It's instantiating my class, right?

If not, is there a way to force the init{...}? Or do I have to call a public method (as I have done in my example?)


回答1:

You could make this by using InstanceCreator. My example is in Java (and a bit different case to show the possibilities) but guess you can pick the relevant information into your Kotlin project.

Assume you have a class like:

@Getter
public class MyClass {

    private String name; 
    private String myData; 

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

}

Then you would have test.json like:

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

To have myData deserialized as some other value or to make any other initialozation on deserialization phase you can register an InstanceCreator which would be like:

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

}

Deserializing like:

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

would result into object like:

{
  "name": "My Name",
  "createdBy": "Instance creator put this data"
}
  • 发表于 2019-02-18 20:22
  • 阅读 ( 188 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除