由于各种原因,我需要在android studio中用java反序列化来自寓言F#的json对象。字符串如下:
{"MainForm":{"OriginMerd":{"id":"onMggagerd","number":5,"tests":{"Blod":{"blodid":"1","glucose":52}}}}}
代码:
Stream<Map.Entry<String, String>> flatten(Map<String, Object> map)
{
return map.entrySet()
.stream()
.flatMap(this::extractValue);
}
Stream<Map.Entry<String, String>> extractValue(Map.Entry<String, Object> entry) {
if (entry.getValue() instanceof String) {
return Stream.of(new AbstractMap.SimpleEntry(entry.getKey(), (String) entry.getValue()));
} else if (entry.getValue() instanceof Map) {
return flatten((Map<String, Object>) entry.getValue());
}
return null;
}
@ReactMethod
public void testFunc(String jsonString, Callback cb){
Map<String,Object> map = new HashMap<>();
ObjectMapper mapper = new ObjectMapper();
try {
//convert JSON string to Map
map = mapper.readValue(String.valueOf(jsonString), new TypeReference<Map<String, Object>>() {
});
Map<String, String> flattenedMap = flatten(map)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
for (Map.Entry<String, String> entry : flattenedMap.entrySet()) {
Log.e("flatmap",entry.getKey() + "/" + entry.getValue());
//System.out.println(entry.getKey() + "/" + entry.getValue());
}
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Log.e("JSONSTRING", jsonString);
cb.invoke("OK");
}
首先,我想我应该用对象映射器将其映射成一张地图,我使用对象映射器来获得一张地图,然后我遵循这种方法How to Flatten a HashMap?
然而,这样做的问题是,结果只给了我orginMerd id和blodid,而不是数字或葡萄糖字段。有没有一种优雅的方法来实现这一点呢?不幸的是,我不太精通Java。
发布于 2019-06-26 04:38:41
您只处理json的字符串或映射类型的值的情况:
if (entry.getValue() instanceof String) {
return Stream.of(new AbstractMap.SimpleEntry(entry.getKey(), (String) entry.getValue()));
} else if (entry.getValue() instanceof Map) {
return flatten((Map<String, Object>) entry.getValue());
}
要获得数字或葡萄糖条目,还应该根据从JSON反序列化获得的内容,使用Long
或Integer
处理Number
类型。
这种方法的问题是Integer
和Long
不是String
,实际上是将json条目映射到Stream<Map.Entry<String, String>>
。
使用toString()
可以将数字放入String
变量中:
例如,要同时处理数字和字符串:
final String value = entry.getValue();
if (value instanceof String || value instanceof Number) {
return Stream.of(new AbstractMap.SimpleEntry(entry.getKey(),
value.toString()));
}
else if (value instanceof Map) {
return flatten((Map<String, Object>) value);
}
// you may return null but you will at least log something
else {
LOGGER.warn("field with key {} and value {} not mapped", entry.getKey(), value);
return null;
}
但它也会使地图的内容不清晰,需要在使用之前进行一些检查。
类似地,使用像Stream<Map.Entry<String, Object>>
这样的泛型类型也会产生类似的问题。
因此,我认为您可以考虑使用特定的类来表示您的模型,并在反序列化期间使用它。
Foo foo = mapper.readValue(String.valueOf(jsonString), Foo.class);
其中Foo
是描述预期结构的类。
发布于 2019-06-26 04:36:17
粘贴反序列化here所需的json。选择source-type JSON,取消选择‘允许附加属性’,输入您的包名和类名。它将为您生成适合您的json的Java类(源代码,而不是已编译的.class文件)。
下载生成的源代码,将其放入您的项目中,然后执行以下操作:objectMapper.readValue(string, YourClassName.class);
。YourClassName
是您在站点中输入的类名(不是MainForm
类,请注意,我刚才在测试时掉进了这个陷阱)。
发布于 2019-06-26 04:54:10
在您当前的版本中,您只允许字符串值。您应该将其更改为允许其他简单类型。要确定是否可以使用此方法,请执行以下操作:
private static boolean isSimpleType(Class<?> type) {
return type.isPrimitive() ||
Boolean.class == type ||
Character.class == type ||
CharSequence.class.isAssignableFrom(type) ||
Number.class.isAssignableFrom(type) ||
Enum.class.isAssignableFrom(type);
}
或者查看here,了解有关如何确定类是否简单的更多详细信息。您还可以简单地调整这些方法以满足您的需求。
使用此选项,您可以使用以下内容来拼合地图:
public static Stream<Map.Entry<String, Object>> flatten(Map<String, Object> map) {
return map.entrySet()
.stream()
.flatMap(YourClass::extractValue);
}
private static Stream<Map.Entry<String, Object>> extractValue(Map.Entry<String, Object> entry) {
if (isSimpleType(entry.getValue().getClass())) {
return Stream.of(new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue()));
} else if (entry.getValue() instanceof Map) {
return flatten((Map<String, Object>) entry.getValue());
}
return null;
}
像以前一样叫它:
Map<String, Object> flattenedMap = flatten(map)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
flattenedMap.forEach((key, value) -> System.out.println(key + ": " + value));
https://stackoverflow.com/questions/56761492
复制相似问题