Klasa danych Kotlin firmy Json przy użyciu GSON

105

Mam taką klasę Java POJO:

class Topic {
    @SerializedName("id")
    long id;
    @SerializedName("name")
    String name;
}

i mam taką klasę danych Kotlin

 data class Topic(val id: Long, val name: String)

Jak nadać json keydowolne zmienne kotlin data classpodobne @SerializedNameadnotacje w zmiennych java?

erluxman
źródło
1
Jak to zrobiłeś w Javie? Pokaż przykład.
nhaarman
Co to jest selektor JSON?
voddan
@voddan To, co miałem na myśli przez te selektory json, to łańcuchy, których mogę użyć do wybrania konkretnego obiektu / tablicy json: w moim przypadku „topic”, „id”, „image”. Mam nadzieję, że ci to wyjaśniłem. Dzięki :)
erluxman
@nhaarman Zmieniłem pytanie, mam nadzieję, że to właśnie masz na myśli
erluxman

Odpowiedzi:

227

Klasa danych:

data class Topic(
  @SerializedName("id") val id: Long, 
  @SerializedName("name") val name: String, 
  @SerializedName("image") val image: String,
  @SerializedName("description") val description: String
)

do JSON:

val gson = Gson()
val json = gson.toJson(topic)

z JSON:

val json = getJson()
val topic = gson.fromJson(json, Topic::class.java)
Anton Holovin
źródło
36
Używaj adnotacji tylko wtedy, gdy występuje niezgodność nazwy zmiennej. W przeciwnym razie, tak, niepotrzebne
Vik
3
Moim zdaniem adnotacje pozwalają nam mieć klasy, które po serializacji można wykluczyć lub uwzględnić zmienne. Bardzo przydatne w przypadku modernizacji. Nie powoduje to wysyłania śmieci na serwer. Ponadto, gdy występują zmiany w nazwach zmiennych po stronie serwera, bardziej bolesne jest zmienianie ich bezpośrednio w zmiennej klasy niż w adnotacji.
Deneb Chorny
11
@Vik jedno uwagi jest wasze imiona zmienne mogą być ewentualnie ukrywane (jak w aplikacji na Androida), ale adnotacja zostanie pozostawiony w stanie nienaruszonym
Caleb_Allen
@AntonGolovin Nie mogę przekazać mojej klasy danych z metody Json.Czy muszę zadeklarować swoją klasę danych w pliku java?
Ravi Yadav,
Jeśli to zrobisz, wierzę, że straciłeś formatu JSON, który może powodować IllegalStateException dół drogi
portfoliobuilder
19

Na podstawie odpowiedzi Antona Golovina

Detale

  • Wersja Gson: 2.8.5
  • Android Studio 3.1.4
  • Wersja Kotlin: 1.2.60

Rozwiązanie

Utwórz dowolne dane klasy i dziedzicz interfejs JSONConvertable

interface JSONConvertable {
     fun toJSON(): String = Gson().toJson(this)
}

inline fun <reified T: JSONConvertable> String.toObject(): T = Gson().fromJson(this, T::class.java)

Stosowanie

Klasa danych

data class User(
    @SerializedName("id") val id: Int,
    @SerializedName("email") val email: String,
    @SerializedName("authentication_token") val authenticationToken: String) : JSONConvertable

Z JSON

val json = "..."
val object = json.toObject<User>()

Do JSON

val json = object.toJSON()
Wasilij Bodnarczuk
źródło
Dlaczego używasz SerializedNameadnotacji zamiast strategii nazewnictwa pól, Wasilij?
peterchaula
2
@Peter, ponieważ @SerializedNamepozwoli mi użyć niestandardowych nazw zmiennych, które mogą nie pasować do klucza json. I tak, nie możesz go używać, @SerializedNamejeśli go nie potrzebujesz.
Wasilij Bodnarchuk
2

Możesz użyć podobnego w klasie Kotlin

class InventoryMoveRequest {
    @SerializedName("userEntryStartDate")
    @Expose
    var userEntryStartDate: String? = null
    @SerializedName("userEntryEndDate")
    @Expose
    var userEntryEndDate: String? = null
    @SerializedName("location")
    @Expose
    var location: Location? = null
    @SerializedName("containers")
    @Expose
    var containers: Containers? = null
}

A także w przypadku klasy zagnieżdżonej możesz użyć tego samego, co w przypadku zagnieżdżonego obiektu. Po prostu podaj nazwę Serialize dla klasy.

@Entity(tableName = "location")
class Location {

    @SerializedName("rows")
    var rows: List<Row>? = null
    @SerializedName("totalRows")
    var totalRows: Long? = null

}

więc jeśli otrzymasz odpowiedź z serwera, każdy klucz będzie mapowany z JOSN.

Alos, przekonwertuj List do JSON:

val gson = Gson()
val json = gson.toJson(topic)

ndroid konwertuje z JSON na Object:

val json = getJson()
val topic = gson.fromJson(json, Topic::class.java)
Pawan Soni
źródło