moshi 自定义限定符注释仅在 属性 上序列化 null
moshi custom qualifier annotation to serialise null on one property only
我只想为我的 JSON 正文中正在进行 PUT 的一个 属性 序列化 null。我不想为对象中的任何其他类型序列化 null。型号class是这样的
@Parcel
class User @ParcelConstructor constructor(var college: College?,
var firstname: String?,
var lastname: String?,
var email: String?,
var active: Boolean = true,
var updatedAt: String?,
var gender: String?,
var picture: String?,
var id: String?,
@field: [CollegeField] var collegeInput: String?,
@field: [CollegeField] var otherCollege: String?,)
我只想序列化 collegeInput 和 otherCollege 字段(如果其中任何一个为空)。例如
val user = User(firstname = "foo", lastname=null, collegeInput="abcd", otherCollege = null)
Json 看起来像这样:
{"user":{
"firstname": "foo",
"collegeInput": "abcd",
"otherCollege": null
}}
在 otherCollege 为空的情况下,对象中省略了姓氏,因为默认情况下 moshi 不会序列化空值,这正是我想要的,但 qualifer 字段应使用空值序列化
我尝试使用
class UserAdapter {
@FromJson
@CollegeField
@Throws(Exception::class)
fun fromJson(reader: JsonReader): String? {
return when (reader.peek()) {
JsonReader.Token.NULL ->
reader.nextNull()
JsonReader.Token.STRING -> reader.nextString()
else -> {
reader.skipValue() // or throw
null
}
}
}
@ToJson
@Throws(IOException::class)
fun toJson(@CollegeField b: String?): String? {
return b
}
@Retention(AnnotationRetention.RUNTIME)
@JsonQualifier
annotation class CollegeField
我将适配器添加到 moshi,但它从未被调用
@Provides
@Singleton
fun provideMoshi(): Moshi {
return Moshi.Builder()
.add(UserAdapter())
.build()
}
@Provides
@Singleton
fun provideRetrofit(client: OkHttpClient, moshi: Moshi, apiConfig: ApiConfig): Retrofit {
return Retrofit.Builder()
.baseUrl(apiConfig.baseUrl)
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
}
尝试我要点的方法:
https://gist.github.com/OleksandrKucherenko/ffb2126d37778b88fca3774f1666ce66
在我的例子中,我将 NULL 从 JSON 转换为默认值 double/integer。您可以轻松修改该方法并使其适用于您的特定案例。
p.s。它 JAVA,先将其转换为 Kotlin。
当限定字符串值为 null 时,您的 toJson 适配器方法将 return null,并且 JsonWriter 不会写入 null 值。
这是一个可以安装的限定器和适配器工厂。
@Retention(RUNTIME)
@JsonQualifier
public @interface SerializeNulls {
JsonAdapter.Factory JSON_ADAPTER_FACTORY = new JsonAdapter.Factory() {
@Nullable @Override
public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) {
Set<? extends Annotation> nextAnnotations =
Types.nextAnnotations(annotations, SerializeNulls.class);
if (nextAnnotations == null) {
return null;
}
return moshi.nextAdapter(this, type, nextAnnotations).serializeNulls();
}
};
}
现在,下面就过去了。
class User(
var firstname: String?,
var lastname: String?,
@SerializeNulls var collegeInput: String?,
@SerializeNulls var otherCollege: String?
)
@Test fun serializeNullsQualifier() {
val moshi = Moshi.Builder()
.add(SerializeNulls.JSON_ADAPTER_FACTORY)
.add(KotlinJsonAdapterFactory())
.build()
val userAdapter = moshi.adapter(User::class.java)
val user = User(
firstname = "foo",
lastname = null,
collegeInput = "abcd",
otherCollege = null
)
assertThat(
userAdapter.toJson(user)
).isEqualTo(
"""{"firstname":"foo","collegeInput":"abcd","otherCollege":null}"""
)
}
请注意,您应该使用 Kotlin support in Moshi 来避免 @field:
奇怪的事情。
我只想为我的 JSON 正文中正在进行 PUT 的一个 属性 序列化 null。我不想为对象中的任何其他类型序列化 null。型号class是这样的
@Parcel
class User @ParcelConstructor constructor(var college: College?,
var firstname: String?,
var lastname: String?,
var email: String?,
var active: Boolean = true,
var updatedAt: String?,
var gender: String?,
var picture: String?,
var id: String?,
@field: [CollegeField] var collegeInput: String?,
@field: [CollegeField] var otherCollege: String?,)
我只想序列化 collegeInput 和 otherCollege 字段(如果其中任何一个为空)。例如
val user = User(firstname = "foo", lastname=null, collegeInput="abcd", otherCollege = null)
Json 看起来像这样:
{"user":{
"firstname": "foo",
"collegeInput": "abcd",
"otherCollege": null
}}
在 otherCollege 为空的情况下,对象中省略了姓氏,因为默认情况下 moshi 不会序列化空值,这正是我想要的,但 qualifer 字段应使用空值序列化
我尝试使用
class UserAdapter {
@FromJson
@CollegeField
@Throws(Exception::class)
fun fromJson(reader: JsonReader): String? {
return when (reader.peek()) {
JsonReader.Token.NULL ->
reader.nextNull()
JsonReader.Token.STRING -> reader.nextString()
else -> {
reader.skipValue() // or throw
null
}
}
}
@ToJson
@Throws(IOException::class)
fun toJson(@CollegeField b: String?): String? {
return b
}
@Retention(AnnotationRetention.RUNTIME)
@JsonQualifier
annotation class CollegeField
我将适配器添加到 moshi,但它从未被调用
@Provides
@Singleton
fun provideMoshi(): Moshi {
return Moshi.Builder()
.add(UserAdapter())
.build()
}
@Provides
@Singleton
fun provideRetrofit(client: OkHttpClient, moshi: Moshi, apiConfig: ApiConfig): Retrofit {
return Retrofit.Builder()
.baseUrl(apiConfig.baseUrl)
.client(client)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
}
尝试我要点的方法:
https://gist.github.com/OleksandrKucherenko/ffb2126d37778b88fca3774f1666ce66
在我的例子中,我将 NULL 从 JSON 转换为默认值 double/integer。您可以轻松修改该方法并使其适用于您的特定案例。
p.s。它 JAVA,先将其转换为 Kotlin。
当限定字符串值为 null 时,您的 toJson 适配器方法将 return null,并且 JsonWriter 不会写入 null 值。
这是一个可以安装的限定器和适配器工厂。
@Retention(RUNTIME)
@JsonQualifier
public @interface SerializeNulls {
JsonAdapter.Factory JSON_ADAPTER_FACTORY = new JsonAdapter.Factory() {
@Nullable @Override
public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) {
Set<? extends Annotation> nextAnnotations =
Types.nextAnnotations(annotations, SerializeNulls.class);
if (nextAnnotations == null) {
return null;
}
return moshi.nextAdapter(this, type, nextAnnotations).serializeNulls();
}
};
}
现在,下面就过去了。
class User(
var firstname: String?,
var lastname: String?,
@SerializeNulls var collegeInput: String?,
@SerializeNulls var otherCollege: String?
)
@Test fun serializeNullsQualifier() {
val moshi = Moshi.Builder()
.add(SerializeNulls.JSON_ADAPTER_FACTORY)
.add(KotlinJsonAdapterFactory())
.build()
val userAdapter = moshi.adapter(User::class.java)
val user = User(
firstname = "foo",
lastname = null,
collegeInput = "abcd",
otherCollege = null
)
assertThat(
userAdapter.toJson(user)
).isEqualTo(
"""{"firstname":"foo","collegeInput":"abcd","otherCollege":null}"""
)
}
请注意,您应该使用 Kotlin support in Moshi 来避免 @field:
奇怪的事情。