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.