Unable to find JsonFormat class in Android · Issue #276 · google/protobuf-gradle-plugin · GitHub
Androidでprotobuf-liteを利用したまま、JSONをオブジェクトにする必要があったので、Gsonで頑張ることにした。InternalなAPIを呼ぶ必要があり困っている。ちなみに grpc/grpc-swiftは頑張る必要もなくシュッと出来ます。
- protoで定義されたフィールドは、生成されたクラスのメンバー変数では最後に
_
がつく
- 例えば、
name
というフィールドを持ってるとすると生成されたクラスのメンバー変数では name_
になる
- protoで定義されたフィールドでリピートするものは、ただのListではなく
Internal.ProtobufList<T>
で表現されている
以上をふまえて、以下のようなコードを書いた。
package com.google.protobuf
open class ProtobufListTypeAdapter<T>(val parser: (JsonElement) -> Collection<T>): TypeAdapter<Internal.ProtobufList<T>>() {
override fun write(out: JsonWriter?, value: Internal.ProtobufList<T>?) {
}
override fun read(jsonReader: JsonReader): Internal.ProtobufList<T> {
val list = ProtobufArrayList<T>()
list.addAll(parser(JsonParser().parse(jsonReader)))
return list
}
}
class DeliveryTimeListTypeAdapter: ProtobufListTypeAdapter<DeliveryTimeOuterClass.DeliveryTime>({
it.asJsonArray.map { element ->
DeliveryTimeOuterClass.DeliveryTime.newBuilder()
.build()
}
})
ProtobufArrayList
が、com.google.protobuf内でしか利用できないので、package com.google.protobuf
にしている。
class ProtoExclusionStrategy: ExclusionStrategy {
override fun shouldSkipClass(clazz: Class<*>?): Boolean {
return false
}
override fun shouldSkipField(f: FieldAttributes?): Boolean {
if (f == null) {
return true
}
return !isProtoField(f.name)
}
fun isProtoField(name: String): Boolean {
return name.contains("_")
}
}
val gson = GsonBuilder()
.setFieldNamingStrategy { it.name.replace("_", "") }
.setExclusionStrategies(ProtoExclusionStrategy())
.registerTypeAdapter(
object : TypeToken<Internal.ProtobufList<DeliveryTimeOuterClass.DeliveryTime>>(){}.type,
DeliveryTimeListTypeAdapter()
)
.create()
gson.fromJson(...)
もっといい方法があったら知りたい。