3

I have a data class like this:

data class TestModel(
     val id: Int, 
     val description: String, 
     val picture: String)

If I create JSON from this data class using GSON and it generates a result like this

{"id":1,"description":"Test", "picture": "picturePath"}

What to do if I need the following JSON from my data class:

{"id":1, "description":"Test"}

And other times:

`{"id":1, "picture": "picturePath"}

` Thanks in advance!

1
  • 1
    given your use of the GSON tag, I added GSON to the title and text to make it clear that this was a GSON specific question. Commented Nov 27, 2018 at 14:13

3 Answers 3

2

You can solve this problem with writing custom adapter and with optional types:

import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.TypeAdapter
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter

data class TestModel(
    val id: Int,
    val description: String? = "",
    val picture: String? = "")

class TesModelTypeAdapter : TypeAdapter<TestModel>() {
    override fun read(reader: JsonReader?): TestModel {
        var id: Int? = null
        var picture: String? = null
        var description: String? = null

        reader?.beginObject()
        while (reader?.hasNext() == true) {
            val name = reader.nextName()

            if (reader.peek() == JsonToken.NULL) {
                reader.nextNull()
                continue
            }

            when (name) {
                "id" -> id = reader.nextInt()
                "picture" -> picture = reader.nextString()
                "description" -> description = reader.nextString()
            }
        }
        reader?.endObject()

        return when {
            !picture.isNullOrBlank() && description.isNullOrBlank() -> TestModel(id = id ?: 0, picture = picture)
            !description.isNullOrBlank() && picture.isNullOrBlank() -> TestModel(id = id ?: 0, description = description)
            else -> TestModel(id ?: 0, picture, description)
        }
    }

    override fun write(out: JsonWriter?, value: TestModel?) {
        out?.apply {
            beginObject()

            value?.let {
                when {
                    !it.picture.isNullOrBlank() && it.description.isNullOrBlank() -> {
                        name("id").value(it.id)
                    name("picture").value(it.picture)
                    }
                    !it.description.isNullOrBlank() && it.picture.isNullOrBlank() -> {
                        name("id").value(it.id)
                    name("description").value(it.description)
                    }
                    else -> {
                        name("id").value(it.id)
                        name("picture").value(it.picture)
                    name("description").value(it.description)
                    }
                }
            }

            endObject()
        }
    }
}

class App {
    companion object {
        @JvmStatic fun main(args: Array<String>) {
            val tm = TestModel(12, description = "Hello desc")
            val tm2 = TestModel(23, picture = "https://www.pexels.com/photo/daylight-forest-glossy-lake-443446/")
            val tm3 = TestModel(12, "Hello desc", "https://www.pexels.com/photo/daylight-forest-glossy-lake-443446/")

            val gson = GsonBuilder().registerTypeAdapter(TestModel::class.java, TesModelTypeAdapter()).create()

            System.out.println(gson.toJson(tm))
            System.out.println(gson.toJson(tm2))
            System.out.println(gson.toJson(tm3))
        }
    }
}

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

1

Here is actually a way to ignore fields, that are not marked via @Exposed annotation. In order for this to work, special configuration should be used when instantiating Gson. Here is how you can to this.

Easy way is to mark the field as @Transient. Then it would not be either serialized and deserialized.

7 Comments

I edited my question Expose and Transient are ignoring my field always, i need to create dynamically json
Have you considered a variant of manual implementation of JsonSerializer then? static.javadoc.io/com.google.code.gson/gson/2.6.2/com/google/…
Thank you for yr quick reply. I think, It is a last chance, but i need easy way from developers who have faced already?
For example in Java, i create multiple constructor then generate gson with constructor fields which i wanted.
It's the same bytecode received from Kotlin source code after compilation as Java's... Writing secondary constructors didn't help?
|
1

I want to give you alternative ways without manually serialization/deserialization.

data class TestModel(
    val id: Int,
    val description: String? = null,
    val picture: String? = null)

When you create json from data class

val params = TestModel(id = 1, description = "custom text")

or

val params = TestModel(id = 1, picture = "picture path")

If one of them field is null of data class GSON skips that field automatically.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.