我想将具有未知/可变字段名和结构嵌套JSONMap转换为通用和多态Java数据结构。
澄清:多态仅表示字符串、HashMap或数组列表。
下面是一个JSON示例,请注意key-names和structure是变量:
{"k1":{"k2":["1","2"], "k3":{"k4":"v4","k5":"v5"}, "k6":"v6"}
我已经用Gson实现了它,它用于创建嵌套的Java散列表,但它试图将值转换为Java基本类,例如Double,整数等等,这不仅它做得很不好(例如,timestamp long到Double),但这是不必要的,因为我所需要的只是将所有值转换为String,除非它们是Map或数组。我猜Object
被取得太自由了。我用了这个:
@SerializedName("data")
HashMap<String,Object> data;
我在这里问了一个关于这个问题的问题Retrofit2, Gson, Java: Parse received JSON values as String, only,它收集了反对票,但没有一点点智慧。
现在,我尝试使用莫希,内容如下:
@JsonClass(generateAdapter = true)
public HashMap<String, Object> data;
但仍然没有喜悦,因为它抱怨java.lang.IllegalArgumentException: Unable to create converter ...
所以,我在这个问题上寻找指导。我很容易,我不需要把JSON转换成POJO。对于这个例子,把JSON转换成HashMap<String,Object>
就足够了。我很容易使用这个工具:Gson,莫希或者我自己定制的JSON -〉嵌套的多态HashMap。有什么建议或者想法吗?
2条答案
按热度按时间zaq34kh61#
在Gson中,不可能覆盖
Object
类型适配器,因此没有直接的方法来反序列化公共类型下的字符串、列表和Map。但是,您可以假设它们三个可以有一个公共的超类型,通过引入标记类型来欺骗类型系统,例如,只标记共同之处的注解。虚设的通用型别标记只会作用于最上层的fromJson
呼叫,而不会我不适用于真正强类型的字段,但正如您在问题中提到的,您并不需要它们。第一个
上面的类型适配器检查给定的类型是否是伪超类型,然后根据实际的JSON标记反序列化为三种类型:
nextString
强制数字和布尔值);我稍微修改了JSON以显示数字将被强制转换为字符串:
以下测试将通过:
无Gson,但有
org.json
溶液正如我在注解中提到的,您可以避免使用Gson反序列化/序列化工具,并完全手动地反序列化给定的JSON:
这就是如何将其添加到Retrofit而不是Gson转换器工厂:
icnyk63a2#
希望这能帮助那些不想使用
Gson
或Moshi
,而想用一个简单的JSON解析器将JSON字符串转换为多态的(多型?)LinkedHashMap
。多态性是指它只包含String
,Array
和Map
。我个人更喜欢这一点,而不是大量的POJO。@Fluffy上面演示了如何使用Gson
创建上述多态Map。但是,同时删除Gson
并使用org.json
也是很有诱惑力的。@Fluffy也提供了这种解决方案。因此,同样,这个解决方案是基于@Fluffy上面的答案,但我还添加了创建一个在返回的Map上构造的自定义对象(这样我就不会一直对某些字段进行类型转换)。我刚刚修改了这个方法(
BaseResponse3
是我的容器类):我处理的第二件事是在... android中使用这段代码。哎哟。看起来android已经内置了具有相同命名空间的
json.org
支持。而且它做了一些修改。例如,它没有JSONTokener(Reader ...)
构造函数。下面是我发布的一个关于这个问题的问题:org.json.JSONTokener : no constructor from Reader因此,我必须使用一个“真实的的”
org.json
(在我的例子中是https://github.com/stleary/JSON-java),我必须将其名称空间修改为org.json.XYZ
,并创建一个JAR(在我的Linux朋友的帮助下自动化了所有操作)。通过将此JAR添加到build.gradle
(项目)中,该JAR被包含在Android Studio中:并将此转换为
build.gradle
(应用程序):我现在按照@Fluffy的说明将这个JSON解析器合并到Retrofit中,使用:
一切都很好。
尽管很可能存在性能问题(* 到目前为止,我还没有注意到 *)因为Android的
org.json
可能会进行某种修改,以比普通的org.json
或Gson
更高效地处理JSON数据流,从而更高效地与OkHttp交互。我很高兴我从另一个依赖的魔爪中逃脱了,我没有设法告诉它 ^&^%& 停止将每个JSON字符串转换为Java基本类型。我以一种荒谬的状态结束了,将整数转换为浮点数,将时间戳(长)转换为...双精度!!!!!使用org.json
,我完全控制了。谢谢@Fluffy。