[Not solved] is it possible to have multiple Seria...
# serialization
w
[Not solved] is it possible to have multiple SerialName for a single class?
Copy code
@Serializable
@SerialName("video")
data class Video(
  val title: String,
  val videoId: String,
...
) : Result
j
@JsonNames(...)
w
This annotation is not applicable to target 'class'.
j
tbh I haven't used
@SerialName
over classes, only over properties
I don't even know it was possible, and I am not sure what happens if on the field is used a different name than over the class. Probably it is not a good pattern with combined the class with networking
w
can you expand on combined the class with networking?
j
a class can be shared with multiple endpoints, which can be using a different name per endpoint. If you put the SerialName on each field, you are good. The use case of having multiple names in the same endpoint is an IMO, bad backend implementation so you have to workaround it with JsonNames, but you have no choice, for the other part you have the choice to use field over class
w
To give more context, I'm doing polymorphic deserialization that's what @SerialName on a class is good for. Also, I'm not doing backend, I only consume a third party RESTapi. I'm on Android
Having a different Video class for each endpoint JSON that has different 'type' field IMO is outrageous
j
I was talking from the client perspective, no backend
w
JsonNames are no good for this usecase
the endpoint returns mixed data not the typical Products, Users scenario (noSQL?)
But thanks for your input.
j
I didn't talk about having two different classes, but using SerialName over the class instead of over the field
w
Then I don't follow what you're trying to say. Having @SerialName("video") over the class Is my problem. Having @SerialName("video", "shortVideo", "longVideo", ...) would solve my problem.
j
don’t use SerialName over the class and your problem is gone
w
then how do you deserialize a mixed data endpoint with the 'type' field in every item in that json list?
j
If I have understood correctly, something like this?
Copy code
data class Response(@JsonNames("foo", "bar") val fooBar: FooBar)

sealed class FooBar {
  data class Foo(val foo: Foo) : FooBar()
  data class Bar(val bar: Bar) : FooBar()
}
With the json response/s maybe I can help more
as my previous answer, in my mind, would be better so
Copy code
data class Response(@SerialName("foo") val foo: FooBar, @SerialName "bar") val bar: FooBar)

// or even
data class Response(@SerialName("foo") val foo: Foo, @SerialName("bar") val bar: Bar)

sealed class FooBar {
  data class Foo(val foo: Foo) : FooBar()
  data class Bar(val bar: Bar) : FooBar()
}
So I can be missing something
w
Copy code
/*
[
  {
    type: "type1",
    title: String,
    ...
  },
  {
    type: "type2",
    title: String,
    ...
  },
  {
    type: "type3",
    title: String,
    ...
  }
]
 */
this is the JSON response
the potential problem is when you have for example type1 and type 2 having the common fields in a class because they are the same entity (say User), but some times you don't need age or weight or...
j
That could be enough:
Copy code
sealed class Foo {
    data class(val type: Type1, val title: String, ...) : Foo()
    data class(val type: Type2, val title: String, ...) : Foo()
    data class(val type: Type3, val title: String, ...) : Foo()
}
But probably you can extract common fields:
Copy code
sealed class Foo<T> {
    abstract val type: T
    abstract val title: String
    ...
}
if the field
type
is changing the name, then:
Copy code
sealed class Foo {
    data class(val type1: Type1, val title: String, ...) : Foo()
    data class(val type2: Type2, val title: String, ...) : Foo()
    data class(val type3: Type3, val title: String, ...) : Foo()
}
w
so that's a lot of code, do yo agree?
if @SerialName("type1") takes multiple values, I can make one class with all the possible fields but nullable
j
You can't avoid it I think
w
we can if we have @SerialName("t1", "t2", ...)
j
let me think
w
ok take your time + thanks for you efforts
j
you need to change the structure and maybe you can get less code maybe something so:
Copy code
val list: List<Foo> // backend response

data class Foo(
    @JsonNames("type1", "type2", ...) val type: Type,
    val title: String,
    ...
)

sealed class Type {
    data class Type1(...) : Type()
    data class Type1(...) : Type()
    ...
}
w
it doesn't really solve the fact that I need to have multiple classes for the same thing aka multiple crazy names. If im gonna have that, I think I rather have @SerialName("type1") class Type1, @SerialName("type2") class Type2 ..
with no inheritance no crazy generics, just plain data classes, but it's still lot of code for one thing
a
the SerialName isn’t really used in JSON edit for classes, because JSON objects don’t have a name. Compare with something like XML, where the tag is kind of equivalent to the SerialName. SerialName is important to KxS internal functioning though, and it should be distinct. Why do you want to have multiple serial names though? The JSON you provided can be parsed by a single class
j
@SerialName
is used on fields, over classes I haven't tried
a
oops, you’re right, I meant on classes.
@SerialName
is used for JSON properties, and also to determine the
type
field for polymorphic objects.
w
@Adam S I don't know if you understood what my problem was. TL;DR I want this @SerialName("t1", "t2", ...) over classes not properties, maybe that would be a good feature to add to the lib, but the thing is people are so used to just creating new classes and call it decoupling or whatever, maybe that's why it is not requested nor implemented. Thanks for ur input.
a
yeah, maybe I didn’t understand :) for the example you gave,
Copy code
@Serializable
@SerialName("video")
data class Video(
  val title: String,
  val videoId: String,
) : Result
if I use this to serialize some data
Copy code
fun main() {
  val video = Video(title = "Star Wars", videoId = "001011101")

  println(Json.encodeToString(video))
}
I’d end up with
Copy code
{
  "title": "Star Wars",
  "videoId": "001011101"
}
and there’s no reference to
@SerialName("video")
, because JSON objects don’t have names. Where should the
@SerialName("video")
be used? Where should it go in the JSON?
w
you need to look at the json I provided to see the full picture
Copy code
/*
[
  {
    type: "type1",
    title: String,
    ...
  },
  {
    type: "type2",
    title: String,
    ...
  },
  {
    type: "type3",
    title: String,
    ...
  }
]
 */
when I first asked i didn't provide it because i assumed it's clear since I used SerialName on the class but ok.
so "type1" would be "video" for example etc..
a
I saw the JSON, but it doesn’t help me understand, because it’s got different fields names to the Kotlin data class you shared, and it’s not valid JSON, and it doesn’t need to be polymorphic https://kotlinlang.slack.com/files/U01681FLZC2/F0546H08TCP/sample.kt.cpp
can you share the complete JSON data you’re trying to parse?
652 Views