Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(Moshi in kotlin) @Json vs @field:Json

Tags:

json

kotlin

moshi

Serialization does not happen properly when I use @Json in the fields but it started working after changing to @field:Json.

I came through this change after reading some bug thread and I think this is specific to kotlin. I would like to know what difference does @field:Json bring and is it really specific to kotlin?

like image 699
Jegan Babu Avatar asked Jul 10 '19 18:07

Jegan Babu


People also ask

What is Moshi JSON?

Moshi is a modern JSON library for Android and Java from Square. It can be considered as the successor to GSON, with a simpler and leaner API and an architecture enabling better performance through the use of the Okio library.

Is Moshi faster than GSON?

✅PerformanceMoshi is way faster than Gson(Link1, ) and uses less memory, This is due to its usage of Okio which can predict or expect ahead of the time the keys which helps on ignoring the unknown or unwanted fields while parsing a stream (A good article on this).

What is Moshi for?

Moshi is a modern JSON library for Android, Java and Kotlin. It makes it easy to parse JSON into Java and Kotlin classes: Note: The Kotlin examples of this README assume use of either Kotlin code gen or KotlinJsonAdapterFactory for reflection.

How does Moshi work with JSON?

Moshi encodes it naturally (as =) and assumes that the HTML encoder – if there is one – will do its job. Moshi works best when your JSON objects and Java or Kotlin classes have the same structure. But when they don't, Moshi has annotations to customize data binding. Use @Json to specify how Java fields or Kotlin properties map to JSON names.

How do I convert a Kotlin class to JSON?

If your Kotlin class has a superclass, it must also be a Kotlin class. Neither reflection or codegen support Kotlin types with Java supertypes or Java types with Kotlin supertypes. If you need to convert such classes to JSON you must create a custom type adapter. The JSON encoding of Kotlin types is the same whether using reflection or codegen.

How do I use Moshi’s Kotlin Codegen support?

Moshi’s Kotlin codegen support can be used as an annotation processor (via kapt) or Kotlin SymbolProcessor ( KSP ). It generates a small and fast adapter for each of your Kotlin classes at compile-time. Enable it by annotating each class that you want to encode as JSON:

How do I connect Moshi to a data class?

To hook it all up and parse the json to the data class you need to create a Moshi object, create the adapter instance and then pass the JSON to the adapter: If the JSON response changes and sets a null field in the JSON then the adapter will fail respecting the non null reference of a val property in the data class and throw a clear exception.


Video Answer


1 Answers

Whatever you put between @ and : in your annotation specifies the exact target for your Annotation.

When using Kotlin with JVM there is a substantial number of things generated, therefore your Annotation could be put in many places. If you don't specify a target you're letting the Kotlin compiler choose where the Annotation should be put. When you specify the target -> you're in charge.

To better see the difference you should inspect the decompiled Java code of the Kotlin Bytecode in IntelliJ/Android Studio.


Example kotlin code:

class Example {

    @ExampleAnnotation
    val a: String = TODO()

    @get:ExampleAnnotation
    val b: String = TODO()

    @field:ExampleAnnotation
    val c: String = TODO()
}

Decompiled Java code:

public final class Example {
   @NotNull
   private final String a;
   @NotNull
   private final String b;
   @ExampleAnnotation
   @NotNull
   private final String c;

   /** @deprecated */
   // $FF: synthetic method
   @ExampleAnnotation
   public static void a$annotations() {
   }

   @NotNull
   public final String getA() {
      return this.a;
   }

   @ExampleAnnotation
   @NotNull
   public final String getB() {
      return this.b;
   }

   @NotNull
   public final String getC() {
      return this.c;
   }

   public Example() {
      boolean var1 = false;
      throw (Throwable)(new NotImplementedError((String)null, 1, (DefaultConstructorMarker)null));
   }
}

For more info go to Kotlin docs.

like image 93
Bartek Lipinski Avatar answered Sep 17 '22 07:09

Bartek Lipinski