Using An Annotation To Serialize Null In Moshi With Nested Event
Solution 1:
I've had the same issue and the only solution I found was to make a custom adapter instead of using the SerializeNulls annotation. This way, it will only serialize nulls if the object is null, and serialize it normally with the generated adapter otherwise.
classEventJsonAdapter{
privateval adapter = Moshi.Builder().build().adapter(Event::class.java)
@ToJsonfuntoJson(writer: JsonWriter, event: Event?) {
if (event == null) {
with(writer) {
serializeNulls = true
nullValue()
serializeNulls = false
}
} else {
adapter.toJson(writer, event)
}
}
}
For the generated adapter to work don't forget to annotate the Event class with:
@JsonClass(generateAdapter = true)
The custom adapter can then be added to the moshi builder like this:
Moshi.Builder().add(EventJsonAdapter()).build()
In my case I only needed this for one model in specific. Probably not a good solution if you need it for several, in which case the annotation is more practical, but I'll leave it here since it might help someone else.
Solution 2:
The issue is .serializeNulls()
returns an adapter that serializes nulls
all the way down the tree.
You can simply copy the implementation for .serializeNulls()
and add null check in the toJson
method and only use it if it's null
like this (sorry for my Java):
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonReader;
import com.squareup.moshi.JsonWriter;
import java.io.IOException;
import javax.annotation.Nullable;
publicclassNullIfNullJsonAdapter<T> extendsJsonAdapter<T> {
final JsonAdapter<T> delegate;
publicNullIfNullJsonAdapter(JsonAdapter<T> delegate) {
this.delegate = delegate;
}
@Overridepublic@Nullable
T fromJson(JsonReader reader)throws IOException {
return delegate.fromJson(reader);
}
@OverridepublicvoidtoJson(JsonWriter writer, @Nullable T value)throws IOException {
if (value == null) {
booleanserializeNulls= writer.getSerializeNulls();
writer.setSerializeNulls(true);
try {
delegate.toJson(writer, value);
} finally {
writer.setSerializeNulls(serializeNulls);
}
} else {
delegate.toJson(writer, value);
}
}
@Overridepublic String toString() {
return delegate + ".serializeNulls()";
}
}
and then you can use it in the @JsonQualifier
importstatic java.lang.annotation.RetentionPolicy.RUNTIME;
import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.JsonQualifier;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.reflect.Type;
import java.util.Set;
import javax.annotation.Nullable;
@Retention(RUNTIME)@JsonQualifierpublic@interface SerializeNulls {
JsonAdapter.FactoryJSON_ADAPTER_FACTORY=newJsonAdapter.Factory() {
@Nullable@Overridepublic JsonAdapter<?> create(Type type, Set<? extendsAnnotation> annotations, Moshi moshi) {
Set<? extendsAnnotation> nextAnnotations =
Types.nextAnnotations(annotations, SerializeNulls.class);
if (nextAnnotations == null) {
returnnull;
}
returnnewNullIfNullJsonAdapter(moshi.nextAdapter(this, type, nextAnnotations));
}
};
}
Post a Comment for "Using An Annotation To Serialize Null In Moshi With Nested Event"