JSON dizesini Jackson JSON ile bir Map <String, String> biçimine dönüştürme


185

Ben böyle bir şey yapmaya çalışıyorum ama işe yaramıyor:

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

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

Ancak IDE diyor ki:

İşaretlenmemiş ödev Map to Map<String,String>

Bunu yapmanın doğru yolu nedir? Sadece Jackson'ı kullanıyorum çünkü projede zaten mevcut olan bu, JSON'a / JSON'dan dönüştürmenin yerel bir Java yolu var mı?

PHP basitçe json_decode($str)ve bir dizi geri almak istiyorum. Burada temelde aynı şeye ihtiyacım var.


JacksonUtils sınıfı nereden geliyor? Jackson'ın hiçbirinde bunu görmüyorum.
— Rob Heiser

Jackson için sargımız, yapmanız gereken bazı JsonFactory ve ObjectMapper öğelerini işliyor.
— adamJLev

1
Yani, sorun JacksonUtils.fromJSON () Eşleme <Dize, Dize> değil, sadece Harita döndürmek için bildirildi olmasıdır.
— Rob Heiser

7
Btw, ilk satırda yeni HashMap atamayın: bu yok sayılır. Sadece çağrıyı değerlendiriyorum.
— StaxMan

Başlığın, tarif edilmemiş sorunla ilgisi yoktur, bu da türlenmemiş koleksiyonla ilgilidir. Aşağıdaki cevap, gerçekten sormaya çalıştığınız sorunun doğru cevabıdır.
— Jukka Dahlbom

Yanıtlar:


313

Aşağıdaki kodu aldım:

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

Bir dosyadan okuyor, ancak bir mapper.readValue()de kabul edecek ve aşağıdakileri kullanarak bir dizeden InputStreambir alabilirsiniz InputStream:

new ByteArrayInputStream(astring.getBytes("UTF-8")); 

Blogumdaki haritacı hakkında biraz daha açıklama var .


2
@Suraj, belgelere göre ve kabul ediyorum ki formülasyonu ilk prensiplerden çıkaramazdım. Java'nın düşündüğümüzden daha karmaşık olduğunu göstermek o kadar garip değil.
— djna

1
Krige: Sabit
— parçanın

2
Küçük bir yorum: ilk oluşturma satırına JsonFactorygerek yoktur. ObjectMapperotomatik olarak kendi başına oluşturabilir.
— StaxMan

1
@djna poster istedi Map<String, String>ve siz sağladınız Map<String, Object>.
— anon58192932

Haritayı bir dize olarak yazmak içinmapper.writeValueAsString(hashmap)
— Zaheer

53

Deneyin TypeFactory. İşte Jackson JSON (2.8.4) kodu.

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'un eski bir sürümünün kodu.

Map<String, String> result = new ObjectMapper().readValue(
    data, TypeFactory.mapType(HashMap.class, String.class, String.class));

38
TypeFactory.mapType (...) artık kullanımdan kaldırıldı, şunu deneyin: yeni TypeReference <HashMap <Dize, Dize >> () {}
— cyber-monk

2
@ cyber-monk Bu uyarılardan kurtulur, ancak aslında türleri kontrol etmez.
— David Moles

26

Aldığınız uyarı derleyici tarafından yapılır, kütüphane (veya yardımcı program yöntemi) tarafından değil.

Jackson'ı doğrudan kullanmanın en basit yolu:

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

Aradığınız yöntem muhtemelen buna benzer bir şey yapar.


OP istedi Map<String, String>ve siz sağladınız Map<String, Object>.
— anon58192932

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

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

readerÖrneğin İş Parçacığı Kasası olduğunu unutmayın .


@dpetruha OP istedi Map<String, String>ve siz sağladınız Map<String, Object>.
— anon58192932

10

Dize'den JSON Haritasına Dönüştürme:

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

ObjectMapper mapper = new ObjectMapper();

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

4
Yukarıdakiler hala sonuçlanmaktadır Type safety: The expression of type HashMap needs unchecked conversion to conform to Map<String,String>. Bu @SuppressWarningsek açıklama ile bastırılabilir olsa TypeReferenceda, Staxman
— Karthic Raghupathi

1
Tip güvenlik uyarısından kurtulmak için, map = mapper.readValue(string, map.getClass());burada olduğu gibi haritayı başlattığınız takdirde kullanabilirsiniz.
— MJV

var türü Map <Integer, String> ise, Nesne sınıfının doğru olmaması yeterlidir.
— Jiayu Wang

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

bence bu sorununuzu çözecek.


1
java doc: since 2.5 - ama muhtemelen 2.7 veya 2.8'de kullanımdan kaldırılacak (2.7 ile gerekli değil)
— Al-Mothafar

3

Aşağıdakiler benim için çalışıyor:

Map<String, String> propertyMap = getJsonAsMap(json);

nerede getJsonAsMapşöyle tanımlanır:

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

Bu o Not olacak size json çocuk nesneleri varsa başarısız (onlar değil, çünkü Stringonlar başka konum HashMap), ama json şöyle özelliklerinin önemli bir değer listesi ise çalışacaktır:

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

3

Google'ın Gson'unu kullanma

Neden Google'ın Gson'unu burada belirtildiği gibi kullanmıyorsunuz ?

Çok ileri ve işi benim için yaptı:

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

1
Kabul etti, dünya ilerledi, Gson çok daha kolay.
— djna

1

İşte bu sorunun genel çözümü.

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

Umarım bir gün birisi herhangi bir Anahtar / değer Harita türüne dönüştürmek için bir util yöntemi oluşturmayı düşünür.


-1

sadece Kotlin'e cevap vermek istedim

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

hmmm, bunun neden reddedildiğinden emin değilim. Bu hat sadece benim için değil, aynı zamanda doğru şekilde yapmanın anahtarıdır. Map <String, String> öğesini istediğiniz farklı bir türle değiştirerek, haritacı dizeyi <MyObject> Listesi veya Liste <Harita <Dize, MyObject >>
— Dustin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.