我正在使用Google HTTP客户端发出API请求,我希望使用parseAs()
方法为我反序列化JSON响应。我的模型是Kotlin数据类,但反序列化器无法实例化我的类:
Caused by: java.lang.IllegalArgumentException: unable to create new instance of class com.ippontech.blog.stats.model.GitFile because it has no accessible default constructor
这是我的Kotlin数据类:
data class GitFile(
val name: String,
@SerializedName("download_url") val downloadUrl: String)
我使用的代码:
val requestFactory = NetHttpTransport().createRequestFactory{
it.setParser(JsonObjectParser(GsonFactory()))
}
val request = requestFactory.buildGetRequest(
GenericUrl("https://api.github.com/repos/ippontech/blog-usa/contents/posts"))
val type = object : TypeToken<List<GitFile>>() {}.type
val rawResponse = request.execute().parseAs(type)
另一方面,如果我将响应作为字符串检索,然后使用Gson解析器,它可以正常工作:
val requestFactory = NetHttpTransport().createRequestFactory()
val request = requestFactory.buildGetRequest(
GenericUrl("https://api.github.com/repos/ippontech/blog-usa/contents/posts"))
val rawResponse = request.execute().parseAsString()
val type = object : TypeToken<List<GitFile>>() {}.type
val gitFiles: List<GitFile> = Gson().fromJson(rawResponse, type)
这似乎表明JsonObjectParser
在这里并没有完全发挥作用。
我正在使用的版本:
compile 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.30'
compile 'com.google.code.gson:gson:2.8.0'
compile 'com.google.apis:google-api-services-sheets:v4-rev512-1.23.0'
compile 'com.google.api-client:google-api-client-gson:1.23.0'
有关如何解决这个问题的想法吗?
答案 0 :(得分:0)
这是因为基础JsonObjectParser
方法在{/ p>中使用newInstance
public static <T> T newInstance(Class<T> clazz) {
try {
return clazz.newInstance();
} catch (IllegalAccessException var2) {
throw handleExceptionForNewInstance(var2, clazz);
} catch (InstantiationException var3) {
throw handleExceptionForNewInstance(var3, clazz);
}
}
虽然你的GitFile
只有一个非默认构造函数(no-args),但它清楚地告诉你。
从一个角度来看,您可以添加如下默认值:
data class GitFile(
val name: String,
@SerializedName("download_url") val downloadUrl: String
) {
constructor() : this(name = "", downloadUrl = "")
}
这不会失败,但似乎工作错误:解析的对象属性对我来说都是null
(我在配置JsonObjectParser
实例时不知道我缺少什么)。
Gson不需要默认构造函数,可以无缝工作。
但它似乎需要一个自定义ObjectParser
实现,我相信,它的工作速度会更快:
class GsonObjectParser(private val gson: Gson) : ObjectParser {
override fun <T : Any?> parseAndClose(inputStream: InputStream?, charset: Charset?, clazz: Class<T>?): T {
return doParseAndClose(InputStreamReader(inputStream, charset), clazz);
}
override fun parseAndClose(inputStream: InputStream?, charset: Charset?, type: Type?): Any {
return doParseAndClose(InputStreamReader(inputStream, charset), type);
}
override fun <T : Any?> parseAndClose(reader: Reader?, clazz: Class<T>?): T {
return doParseAndClose(reader, clazz);
}
override fun parseAndClose(reader: Reader?, type: Type?): Any {
return doParseAndClose(reader, type);
}
private fun <T : Any?> doParseAndClose(reader: Reader?, type: Type?): T {
JsonReader(reader).use {
return gson.fromJson(reader, type);
};
}
}
data class GitFile(
val name: String?,
val downloadUrl: String?
)
fun main(args: Array<String>) {
val gson = GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create();
val requestFactory = NetHttpTransport().createRequestFactory {
it.setParser(GsonObjectParser(gson))
}
val request = requestFactory.buildGetRequest(GenericUrl("https://api.github.com/repos/ippontech/blog-usa/contents/posts"))
val type = object : TypeToken<List<GitFile>>() {}.type
val gitFiles = request.execute().parseAs(type) as List<GitFile>
gitFiles
.stream()
.map { gitFile -> gitFile.name + ": " + gitFile.downloadUrl }
.forEach { gitFile -> System.out.println(gitFile) }
}
截至今天的输出的第一行:
10-tips-and-tricks-for-cassandra.md: https://raw.githubusercontent.com/ippontech/blog-usa/master/posts/10-tips-and-tricks-for-cassandra.md
5-laws-every-developer-should-know.md: https://raw.githubusercontent.com/ippontech/blog-usa/master/posts/5-laws-every-developer-should-know.md
a-journey-into-blockchain-private-network-with-ethereum.md: https://raw.githubusercontent.com/ippontech/blog-usa/master/posts/a-journey-into-blockchain-private-network-with-ethereum.md