如何使用Jackson JSON将JSON字符串转换为Map <String,String>


184

我正在尝试做这样的事情,但它不起作用:

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的任何发行版中都没有看到它。
罗伯·海塞尔

它是Jackson的包装器,处理您必须执行的一些JsonFactory和ObjectMapper东西。
adamJLev

1
因此,问题在于没有声明JacksonUtils.fromJSON()返回Map <String,String>,而是返回Map。
罗伯·海塞尔

7
顺便说一句,不要在第一行分配新的HashMap:这将被忽略。只是打个电话。
StaxMan 2010年

标题与您描述的问题无关,与未类型化的集合有关。下面的答案是您真正想问的正确答案。
Jukka Dahlbom 2012年

Answers:


312

我有以下代码:

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")); 

我的博客上还有关于映射器的更多解释。


2
@Suraj,按照文档进行,我同意我无法从第一条原则中推论得出。并没有显示Java比我们想象的要复杂得多。
djna 2012年

1
克里格(Krige):我以为很难使映射器运行起来,但是我添加了有关如何将技术应用于字符串的说明
djna 2013年

2
一个小评论:JsonFactory不需要创建的第一行。ObjectMapper可以自行自动创建。
StaxMan,2015年

1
@djna发帖人要的Map<String, String>,您已经提供了Map<String, Object>
anon58192932

可以将地图写为字符串mapper.writeValueAsString(hashmap)
Zaheer

53

尝试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));

38
TypeFactory.mapType(...)现在已弃用,请尝试以下操作:new TypeReference <HashMap <String,String >>(){}
网络僧侣

2
@ cyber-monk摆脱了警告,但实际上不检查类型。
David Moles

26

警告您得到的警告是由编译器而不是库(或实用程序方法)完成的。

直接使用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>
anon58192932'7

18
ObjectReader reader = new ObjectMapper().readerFor(Map.class);

Map<String, String> map = reader.readValue("{\"foo\":\"val\"}");

请注意,该reader实例是线程安全的。


@dpetruha OP要求Map<String, String>您提供Map<String, Object>
anon58192932'7

10

从String转换为JSON Map:

Map<String,String> map = new HashMap<String,String>();

ObjectMapper mapper = new ObjectMapper();

map = mapper.readValue(string, HashMap.class);

4
以上结果仍为Type safety: The expression of type HashMap needs unchecked conversion to conform to Map<String,String>。尽管可以通过@SuppressWarnings注释来抑制这种情况,但我建议您TypeReference先使用Staxman所提到的方法
然后再

1
要摆脱类型安全警告,可以使用map = mapper.readValue(string, map.getClass());-假设您已实例化了地图(如此处的情况)。
MJV

如果var的类型为Map <Integer,String>,则仅获取对象类不正确。
王佳瑜

5
JavaType javaType = objectMapper.getTypeFactory().constructParameterizedType(Map.class, Key.class, Value.class);
Map<Key, Value> map=objectMapper.readValue(jsonStr, javaType);

我认为这将解决您的问题。


1
在Java Doc中:@since 2.5-但可能会在2.7或2.8中弃用(2.7不需要)
Al-Mothafar

3

以下对我有用:

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中有子对象(因为它们不是,而是另一个),则此操作失败,但是如果您的json是如下属性的键值列表,则该方法将起作用:StringHashMap

{
    "client_id": "my super id",
    "exp": 1481918304,
    "iat": "1450382274",
    "url": "http://www.example.com"
}

3

使用Google的Gson

为什么不使用这里提到的Google的Gson ?

非常直截了当并为我完成了工作:

HashMap<String,String> map = new Gson().fromJson( yourJsonString, new TypeToken<HashMap<String, String>>(){}.getType());

1
同意,世界在前进,Gson非常容易使用。
djna,

1

这是此问题的通用解决方案。

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);
    }
  }

希望有一天有人会想到创建一个util方法以转换为Map的任何键/值类型,因此此答案:)


-1

只是想给科特林一个答案

val propertyMap = objectMapper.readValue<Map<String,String>>(properties, object : TypeReference<Map<String, String>>() {})

嗯,不知道为什么这被否决了。这条线不仅对我有用,而且还提供了正确方法的关键。通过将Map <String,String>替换为所需的其他类型,映射器会将字符串转换为任何复杂的集合,例如List <MyObject>或List <Map <String,MyObject >>
Dustin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.