简体   繁体   中英

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.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?)

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM