Jackson JSONを使用してJSON文字列をMap <String、String>に変換する方法


185

私はこのようなことをやろうとしていますが、うまくいきません:

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

propertyMap = JacksonUtils.fromJSON(properties, Map.class);

しかしIDEは言う:

未チェックの割り当て Map to Map<String,String>

これを行う正しい方法は何ですか?私はジャクソンのみを使用しています。それはプロジェクトですでに利用可能なものだからです。JSONとの間で変換するネイティブJavaの方法はありますか?

PHPでは、単純にjson_decode($str)配列を取得します。基本的に同じものがここに必要です。


クラスJacksonUtilsはどこから来ていますか?ジャクソンのどのリリースにも見られません。
Rob Heiser、2010年

これは、Jacksonのラッパーであり、JsonFactoryおよびObjectMapperの一部を処理する必要があります。
adamJLev 2010年

1
したがって、問題は、JacksonUtils.fromJSON()がMap <String、String>を返すように宣言されておらず、Mapだけを宣言していることです。
Rob Heiser、2010年

7
ところで、最初の行に新しいHashMapを割り当てないでください。無視されます。電話をかけるだけ。
StaxMan 2010年

タイトルは、記述された問題とは何の関係もありません。これは、型なしコレクションに関係しています。以下の答えは、あなたが実際に尋ねようとしたことに対する正しい答えです。
Jukka Dahlbom

回答:


313

私は次のコードを持っています:

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

2
1つのマイナーなコメント:作成の最初の行はJsonFactory必要ありません。ObjectMapper自動的に作成できます。
StaxMan、2015年

1
@djnaポスターが要求しMap<String, String>、あなたが提供しましたMap<String, Object>
anon58192932 2017

マップを文字列として書き込むには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(...)は非推奨になりました。これを試してください:新しいTypeReference <HashMap <String、String >>(){}
cyber-monk

2
@ cyber-monkこれは警告を取り除きますが、実際にはタイプをチェックしません。
David Moles 2017年

26

警告は、ライブラリ(またはユーティリティメソッド)ではなく、コンパイラによって行われます。

ジャクソンを直接使用する最も簡単な方法は次のとおりです。

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 2017

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 2017

10

文字列からJSONマップへの変換:

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、スタックスマンが述べたように、最初または次のキャストを使用することをお勧めします
Karthic Raghupathi

1
タイプセーフティの警告を取り除くには、次のように使用できますmap = mapper.readValue(string, map.getClass());-ここでのように、マップをインスタンス化した場合。
MJV 2016年

varのタイプがMap <Integer、String>の場合、オブジェクトクラスを取得するだけでは正しくありません。
Jiayu Wang 2017

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に子オブジェクトがある場合、これ失敗します(それらはでないためString、別のものですHashMap)。ただし、jsonが次のようなプロパティのキー値リストである場合は機能します。

{
    "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メソッドを作成してマップの任意のキー/値タイプに変換することを考えているといいので、この答え:)


-1

Kotlinの答えを出したかっただけです

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

うーん、なぜこれが反対票だったのかわからない。このラインは私にとってうまくいくだけでなく、それを正しい方法で行うための鍵も与えます。Map <String、String>を別の目的の型に置き換えることにより、マッパーは文字列をList <MyObject>やList <Map <String、MyObject >>などの複雑なコレクションに変換します
ダスティン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.