วิธีการแปลงสตริง JSON เป็น Map <String, String> ด้วย Jackson JSON


184

ฉันกำลังพยายามทำสิ่งนี้ แต่ไม่ได้ผล:

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

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

แต่ IDE บอกว่า:

งานที่ไม่ได้ตรวจสอบ Map to Map<String,String>

วิธีที่ถูกต้องในการทำเช่นนี้คืออะไร? ฉันใช้แจ็กสันเพียงอย่างเดียวเพราะนั่นคือสิ่งที่มีอยู่ในโครงการแล้วมีวิธี Java ดั้งเดิมของการแปลงเป็น / จาก JSON หรือไม่

ใน PHP ฉันจะเพียงแค่json_decode($str)และฉันจะได้รับอาร์เรย์ ฉันต้องการสิ่งเดียวกันที่นี่


ชั้น JacksonUtils มาจากไหน ฉันไม่เห็นมันในรุ่นใด ๆ ของแจ็คสัน
Rob Heiser

นี่คือเสื้อคลุมสำหรับแจ็คสันของเราจัดการ JsonFactory และ ObjectMapper บางอย่างที่คุณต้องทำ
adamJLev

1
ดังนั้นปัญหาคือ JacksonUtils.fromJSON () ไม่ได้ประกาศว่าจะส่งคืนแผนที่ <String, String> แต่เป็นเพียงแผนที่
Rob Heiser

7
Btw ไม่ได้กำหนด HashMap ใหม่ในบรรทัดแรก: นั่นจะถูกละเว้น เพียงแค่รับสาย
StaxMan

ชื่อไม่มีส่วนเกี่ยวข้องกับปัญหาที่คุณอธิบายซึ่งเกี่ยวข้องกับการรวบรวมที่ไม่ได้พิมพ์ คำตอบด้านล่างนี้เป็นคำตอบที่ถูกต้องสำหรับสิ่งที่คุณพยายามถาม
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")); 

มีคำอธิบายอีกเล็กน้อยเกี่ยวกับ mapper บนเป็นบล็อกของฉัน


2
@Suraj มันเป็นไปตามเอกสารและฉันยอมรับว่าฉันไม่สามารถสรุปสูตรจากหลักการแรกได้ มันไม่แปลกเท่าที่แสดงว่า Java นั้นซับซ้อนกว่าที่เราคิด
djna

1
Krige: ฉันคิดว่าบิตยากที่จะทำให้ mapper เกิดขึ้น แต่ฉันได้เพิ่มหมายเหตุเกี่ยวกับวิธีการใช้เทคนิคกับสตริง
djna

2
หนึ่งความคิดเห็นเล็กน้อย: JsonFactoryไม่จำเป็นต้องสร้างบรรทัดแรก ObjectMapperสามารถสร้างมันขึ้นมาเองโดยอัตโนมัติ
StaxMan

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 (... ) เลิกใช้แล้วลองทำดังนี้: TypeReference <HashMap <String, String >> () {} ใหม่
cyber-monk

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

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

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
Karthic Raghupathi

1
ในการกำจัดคำเตือนความปลอดภัยประเภทคุณสามารถใช้map = mapper.readValue(string, map.getClass());- เนื่องจากคุณได้สร้างอินสแตนซ์ของแผนที่เช่นเดียวกับที่นี่
MJV

ถ้าประเภทของ var คือ Map <Integer, String> เพียงแค่รับคลาสออบเจ็กต์ไม่ถูกต้อง
Jiayu Wang

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

ใช้ Gson ของ Google

ทำไมไม่ใช้ Gson ของ Google ตามที่กล่าวไว้ในที่นี้

ตรงไปตรงมามากและทำงานให้ฉัน:

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

หวังว่าซักวันใครบางคนอาจคิดว่าจะสร้างวิธีการใช้ประโยชน์เพื่อแปลงเป็น Key / Value type ของ Map ดังนั้นคำตอบนี้ :)


-1

แค่อยากจะให้คำตอบ Kotlin

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

อืมไม่แน่ใจว่าทำไมนี่คือ downvote บรรทัดนี้ไม่เพียงทำงานให้ฉันเท่านั้น แต่ยังมอบกุญแจในการทำในสิ่งที่ถูกต้อง ด้วยการแทนที่ Map <String, String> ด้วยประเภทที่ต้องการที่แตกต่างกัน mapper จะแปลงสตริงเป็นคอลเลกชันที่ซับซ้อนเช่น List <MyObject> หรือ List <Map <String, MyObject >>
Dustin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.