如何使用 Jackson JSON 将 JSON 字符串转换为 Map<String, String>
Posted
技术标签:
【中文标题】如何使用 Jackson JSON 将 JSON 字符串转换为 Map<String, String>【英文标题】:How to convert a JSON string to a Map<String, String> with Jackson JSON 【发布时间】:2011-02-01 06:35:22 【问题描述】:我正在尝试做这样的事情,但它不起作用:
Map<String, String> propertyMap = new HashMap<String, String>();
propertyMap = JacksonUtils.fromJSON(properties, Map.class);
但是 IDE 说:
未经检查的分配
Map to Map<String,String>
这样做的正确方法是什么? 我只使用 Jackson,因为这是项目中已经可用的,是否有本地 Java 方式来转换 JSON 或从 JSON 转换?
在 php 中,我只需 json_decode($str)
并返回一个数组。我在这里需要基本相同的东西。
【问题讨论】:
JacksonUtils 类从何而来?我在任何杰克逊版本中都没有看到它。 它是我们对 Jackson 的包装器,处理一些你必须做的 JsonFactory 和 ObjectMapper 的事情。 所以,问题在于 JacksonUtils.fromJSON() 没有声明返回 Map[2020 年 9 月更新] 虽然我多年前的原始答案似乎很有帮助并且仍在获得支持,但我现在使用 Google 的 GSON 库,我发现它更直观。
我有以下代码:
public void testJackson() throws IOException
ObjectMapper mapper = new ObjectMapper();
File from = new File("albumnList.txt");
TypeReference<HashMap<String,Object>> typeRef
= new TypeReference<HashMap<String,Object>>() ;
HashMap<String,Object> o = mapper.readValue(from, typeRef);
System.out.println("Got " + o);
它正在从文件中读取,但mapper.readValue()
也将接受InputStream
,您可以使用以下命令从字符串中获取InputStream
:
new ByteArrayInputStream(astring.getBytes("UTF-8"));
my blog 上有更多关于映射器的解释。
【讨论】:
@Suraj,根据文档,我同意我无法从第一原理中推断出公式。这并不奇怪,因为它表明 Java 比我们想象的要复杂。 Krige:我认为很难让映射器运行起来,但我已经添加了关于如何将该技术应用于字符串的注释 一个小注释:创建JsonFactory
的第一行不需要。 ObjectMapper
可以自己自动创建。
@djna 发帖人要求提供Map<String, String>
,而您提供了Map<String, Object>
。
要将地图写成字符串,你可以这样做mapper.writeValueAsString(hashmap)
【参考方案2】:
试试TypeFactory
。这是 Jackson JSON (2.8.4) 的代码。
Map<String, String> result;
ObjectMapper mapper;
TypeFactory factory;
MapType type;
factory = TypeFactory.defaultInstance();
type = factory.constructMapType(HashMap.class, String.class, String.class);
mapper = new ObjectMapper();
result = mapper.readValue(data, type);
这是旧版 Jackson JSON 的代码。
Map<String, String> result = new ObjectMapper().readValue(
data, TypeFactory.mapType(HashMap.class, String.class, String.class));
【讨论】:
TypeFactory.mapType(...) 现在已弃用,试试这个: new TypeReference您收到的警告是由编译器完成的,而不是由库(或实用程序方法)完成的。
直接使用 Jackson 的最简单方法是:
HashMap<String,Object> props;
// src is a File, InputStream, String or such
props = new ObjectMapper().readValue(src, new TypeReference<HashMap<String,Object>>() );
// or:
props = (HashMap<String,Object>) new ObjectMapper().readValue(src, HashMap.class);
// or even just:
@SuppressWarnings("unchecked") // suppresses typed/untype mismatch warnings, which is harmless
props = new ObjectMapper().readValue(src, HashMap.class);
您调用的实用程序方法可能只是做类似的事情。
【讨论】:
OP 要求提供Map<String, String>
,而您提供了Map<String, Object>
。【参考方案4】:
ObjectReader reader = new ObjectMapper().readerFor(Map.class);
Map<String, String> map = reader.readValue("\"foo\":\"val\"");
注意reader
实例是线程安全的。
【讨论】:
@dpetruha OP 要求提供Map<String, String>
,而您提供了 Map<String, Object>
。【参考方案5】:
从字符串转换为 JSON 映射:
Map<String,String> map = new HashMap<String,String>();
ObjectMapper mapper = new ObjectMapper();
map = mapper.readValue(string, HashMap.class);
【讨论】:
以上结果仍然是Type safety: The expression of type HashMap needs unchecked conversion to conform to Map<String,String>
。虽然这可以通过 @SuppressWarnings
注释来抑制,但我建议先使用 TypeReference
或按照 Staxman 的说明进行下一步
要摆脱类型安全警告,您可以使用map = mapper.readValue(string, map.getClass());
- 假设您已经实例化了地图,就像这里的情况一样。
如果var的类型是MapJavaType javaType = objectMapper.getTypeFactory().constructParameterizedType(Map.class, Key.class, Value.class);
Map<Key, Value> map=objectMapper.readValue(jsonStr, javaType);
我认为这会解决你的问题。
【讨论】:
在 java doc 中:@since 2.5 -- 但可能会在 2.7 或 2.8 中弃用(2.7 不需要)【参考方案7】:以下对我有用:
Map<String, String> propertyMap = getJsonAsMap(json);
getJsonAsMap
的定义如下:
public HashMap<String, String> getJsonAsMap(String json)
try
ObjectMapper mapper = new ObjectMapper();
TypeReference<Map<String,String>> typeRef = new TypeReference<Map<String,String>>() ;
HashMap<String, String> result = mapper.readValue(json, typeRef);
return result;
catch (Exception e)
throw new RuntimeException("Couldnt parse json:" + json, e);
请注意,如果您的 json 中有子对象(因为它们不是 String
,它们是另一个 HashMap
),这将失败,但如果您的 json 是如下属性的键值列表:
"client_id": "my super id",
"exp": 1481918304,
"iat": "1450382274",
"url": "http://www.example.com"
【讨论】:
【参考方案8】:只是想给出一个 Kotlin 的答案
val propertyMap = objectMapper.readValue<Map<String,String>>(properties, object : TypeReference<Map<String, String>>() )
【讨论】:
嗯,不知道为什么这被否决了。这条线不仅对我有用,它还提供了正确方法的关键。通过将 Map使用 Google 的 Gson
为什么不使用here 中提到的 Google 的 Gson?
非常直截了当,为我完成了这项工作:
HashMap<String,String> map = new Gson().fromJson( yourJsonString, new TypeToken<HashMap<String, String>>().getType());
【讨论】:
同意,世界已经在前进,Gson 使用起来要容易得多。【参考方案10】:这里是这个问题的通用解决方案。
public static <K extends Object, V extends Object> Map<K, V> getJsonAsMap(String json, K key, V value)
try
ObjectMapper mapper = new ObjectMapper();
TypeReference<Map<K, V>> typeRef = new TypeReference<Map<K, V>>()
;
return mapper.readValue(json, typeRef);
catch (Exception e)
throw new RuntimeException("Couldnt parse json:" + json, e);
希望有一天有人会考虑创建一个实用方法来转换为任何键/值类型的 Map 因此这个答案:)
【讨论】:
以上是关于如何使用 Jackson JSON 将 JSON 字符串转换为 Map<String, String>的主要内容,如果未能解决你的问题,请参考以下文章
JAVA:如何将 JSON 键值对映射到不同的变量 Jackson
如何使用Jackson JsonGenerator将列表添加到JSON中。
如何使用 Jackson 将 JSON 键值数组动态映射到子对象?