আমি কীভাবে জেসনকে জেসন ব্যবহার করে একটি হ্যাশম্যাপে রূপান্তর করতে পারি?


286

আমি এমন সার্ভার থেকে ডেটা অনুরোধ করছি যা JSON ফর্ম্যাটে ডেটা ফেরত দেয়। অনুরোধ করার সময় জ্যাশনে হ্যাশম্যাপ কাস্ট করা মোটেই কঠিন ছিল না তবে অন্যভাবে কিছুটা জটিল বলে মনে হচ্ছে। জেএসওএন প্রতিক্রিয়াটি এমন দেখাচ্ছে:

{ 
    "header" : { 
        "alerts" : [ 
            {
                "AlertID" : "2",
                "TSExpires" : null,
                "Target" : "1",
                "Text" : "woot",
                "Type" : "1"
            },
            { 
                "AlertID" : "3",
                "TSExpires" : null,
                "Target" : "1",
                "Text" : "woot",
                "Type" : "1"
            }
        ],
        "session" : "0bc8d0835f93ac3ebbf11560b2c5be9a"
    },
    "result" : "4be26bc400d3c"
}

কোন উপায়ে এই ডেটা অ্যাক্সেস করা সবচেয়ে সহজ হবে? আমি জিএসএন মডিউলটি ব্যবহার করছি।


23
Map<String,Object> result = new Gson().fromJson(json, Map.class);gson 2.6.2 এর সাথে কাজ করে।
ফেরান মেলিনঞ্চ

1
কিভাবে ফিরে রূপান্তর? আমি ম্যাপ থেকে জেসন অ্যারে বলতে চাই।
কে.সোফিয়াক

উত্তর:


471

আপনি এখানে যান:

import java.lang.reflect.Type;
import com.google.gson.reflect.TypeToken;

Type type = new TypeToken<Map<String, String>>(){}.getType();
Map<String, String> myMap = gson.fromJson("{'k1':'apple','k2':'orange'}", type);

6
ভাল তবে আমি ব্যবহার করতে পছন্দ করি না TypeToken- এটি ভিতরে অন্তর্ভুক্ত ingালাই করে।
অ্যালিকেলজিন-কিলাকা 26'14

ম্যাপ <> এ কাস্টিং, আপনি আমার হতাশার ঘন্টা শেষ করেছেন!
ডেক্সটার

1
উদাহরণস্বরূপ কি এটি বৈধ জাসন?
ইভান কায়রুজ

@ ইভানকাইরুজ না, এটি হয় না। এটি হওয়া উচিত{"k1":"apple","k2":"orange"}
ভাদিম কোতোভ

আমার যদি স্ট্রিংটি রূপান্তর করতে হবে যা আসলে একটি অ্যারে হয়
রবি যাদব

111

এই কোডটি কাজ করে:

Gson gson = new Gson(); 
String json = "{\"k1\":\"v1\",\"k2\":\"v2\"}";
Map<String,Object> map = new HashMap<String,Object>();
map = (Map<String,Object>) gson.fromJson(json, map.getClass());

1
এটি ইনটগুলিকে স্ট্রিংয়ে রূপান্তরিত করার আগে এটি ফ্লোটে রূপান্তরিত করবে, তবে এটি তুলনামূলক উদ্দেশ্যে JSON কে মানচিত্রে রূপান্তর করতে কাজ করবে।
louielouie

12
আমার জন্য দুর্দান্ত কাজ করে, তবে আমি মানচিত্রটি পরিবর্তিত করেছি Map<String, Object>কারণ জসন যদি কেবল স্ট্রিং না হয় তবে আপনি একটি ত্রুটি পান
মোশে শাহাম

5
এটি ভুল ধারণা দেয়। প্যারামিটারাইজড ধরণের সঠিক সমাধানটি হ'ল TypeToken
সোটিরিওস ডেলিমনলিস

এটি সমস্ত ধরণের সাধারণ সমাধান হবে তবে কিছুটা অস্বাভাবিক।
লিওন

76

আমি জানি এটি মোটামুটি পুরানো প্রশ্ন, তবে আমি নেস্টেড জেএসওএন-এর কাছে জেনারিকভাবে ডিসরিয়ালাইজ করার একটি সমাধান খুঁজছিলাম Map<String, Object>, এবং কিছুই পাইনি।

আমার ইয়ামল ডিজিজারাইজারটি যেভাবে কাজ করে, আপনি Map<String, Object>যখন কোনও প্রকার নির্দিষ্ট না করে তা JSON অবজেক্টগুলিকে ডিফল্ট করে তোলে তবে জিএসন এটি করবে বলে মনে হয় না। ভাগ্যক্রমে আপনি এটি একটি কাস্টম ডিসরিয়ালাইজার দিয়ে সম্পন্ন করতে পারেন।

আমি স্বাভাবিকভাবেই deserialize কিছু নিম্নলিখিত deserializer ব্যবহৃত, খেলাপি JsonObjectকরার গুলি Map<String, Object>এবং JsonArrayগুলি Object[]গুলি, যেখানে সব শিশুদের একভাবে deserialized করছে।

private static class NaturalDeserializer implements JsonDeserializer<Object> {
  public Object deserialize(JsonElement json, Type typeOfT, 
      JsonDeserializationContext context) {
    if(json.isJsonNull()) return null;
    else if(json.isJsonPrimitive()) return handlePrimitive(json.getAsJsonPrimitive());
    else if(json.isJsonArray()) return handleArray(json.getAsJsonArray(), context);
    else return handleObject(json.getAsJsonObject(), context);
  }
  private Object handlePrimitive(JsonPrimitive json) {
    if(json.isBoolean())
      return json.getAsBoolean();
    else if(json.isString())
      return json.getAsString();
    else {
      BigDecimal bigDec = json.getAsBigDecimal();
      // Find out if it is an int type
      try {
        bigDec.toBigIntegerExact();
        try { return bigDec.intValueExact(); }
        catch(ArithmeticException e) {}
        return bigDec.longValue();
      } catch(ArithmeticException e) {}
      // Just return it as a double
      return bigDec.doubleValue();
    }
  }
  private Object handleArray(JsonArray json, JsonDeserializationContext context) {
    Object[] array = new Object[json.size()];
    for(int i = 0; i < array.length; i++)
      array[i] = context.deserialize(json.get(i), Object.class);
    return array;
  }
  private Object handleObject(JsonObject json, JsonDeserializationContext context) {
    Map<String, Object> map = new HashMap<String, Object>();
    for(Map.Entry<String, JsonElement> entry : json.entrySet())
      map.put(entry.getKey(), context.deserialize(entry.getValue(), Object.class));
    return map;
  }
}

handlePrimitiveপদ্ধতির অভ্যর্থনা হ'ল এটি নিশ্চিত করার জন্য যে আপনি কেবল কখনও দ্বিগুণ বা একটি পূর্ণসংখ্যা বা একটি দীর্ঘ পেতে পারেন এবং সম্ভবত এটি আরও ভাল হতে পারে বা কমপক্ষে সরলকরণে যদি আপনি বিগডিসিমালগুলি পেয়ে ঠিক থাকেন তবে আমি বিশ্বাস করি এটি ডিফল্ট।

আপনি এই অ্যাডাপ্টারের মতো নিবন্ধন করতে পারেন:

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Object.class, new NaturalDeserializer());
Gson gson = gsonBuilder.create();

এবং তারপরে এটিকে কল করুন:

Object natural = gson.fromJson(source, Object.class);

আমি নিশ্চিত না যে কেন এটি জিএসএন-এ ডিফল্ট আচরণ নয়, কারণ এটি বেশিরভাগ অন্যান্য আধা-কাঠামোগত সিরিয়ালাইজেশন লাইব্রেরিতে রয়েছে ...


1
... যদিও আমি যে অবজেক্টগুলি ফিরে পাব তার সাথে এখন কী করব তা আমি নিশ্চিত নই। আমি জানি তারা স্ট্রিং করছে যদিও তাদের স্ট্রিং হিসাবে কাস্ট করা যাবে বলে মনে হচ্ছে না
ম্যাট জুকোভস্কি

1
আহা! কৌতুকটি প্রসংগের পরিবর্তে পুনরায় কল্পনা করে ডিসরিওলাইজার ছিল।
ম্যাট জুকোভস্কি

1
আপনার কিছু কোড ম্যাট লাগবে? আমি ডিসরিয়ালেজারে পরিবর্তন আনার চেষ্টা করছি তবে আমি সত্যিই আপনার বক্তব্যটি দেখতে পাচ্ছি না
রোমেন পাইল

5
গসন এখন ডিফল্টরূপে কেভিন দোলন তার কোড স্নিপেটে যে আচরণটি চালাচ্ছে তা উপস্থিত রয়েছে বলে মনে হয়।
এলেট্রোক্রাম

1
@SomeoneSomewhere এখানে উত্তর দেখুন গৃহীত stackoverflow.com/questions/14944419/gson-to-hashmap
আমার

32

গুগলের জিসন ২.7 (সম্ভবত পূর্ববর্তী সংস্করণগুলিও, তবে আমি বর্তমান সংস্করণ ২.7 দিয়ে পরীক্ষা করেছি) এটি এতটা সহজ:

Map map = gson.fromJson(jsonString, Map.class);

যা Mapএক প্রকারের রিটার্ন দেয় com.google.gson.internal.LinkedTreeMapএবং নেস্টেড অবজেক্টস, অ্যারে ইত্যাদিতে পুনরাবৃত্তভাবে কাজ করে

আমি এর মতো ওপি উদাহরণটি চালিয়েছি (কেবলমাত্র একক-কোট এবং সরিয়ে নেওয়া হোয়াইটস্পেসের সাথে ডাবল প্রতিস্থাপন করা হয়েছে):

String jsonString = "{'header': {'alerts': [{'AlertID': '2', 'TSExpires': null, 'Target': '1', 'Text': 'woot', 'Type': '1'}, {'AlertID': '3', 'TSExpires': null, 'Target': '1', 'Text': 'woot', 'Type': '1'}], 'session': '0bc8d0835f93ac3ebbf11560b2c5be9a'}, 'result': '4be26bc400d3c'}";
Map map = gson.fromJson(jsonString, Map.class);
System.out.println(map.getClass().toString());
System.out.println(map);

এবং নিম্নলিখিত আউটপুট পেয়েছেন:

class com.google.gson.internal.LinkedTreeMap
{header={alerts=[{AlertID=2, TSExpires=null, Target=1, Text=woot, Type=1}, {AlertID=3, TSExpires=null, Target=1, Text=woot, Type=1}], session=0bc8d0835f93ac3ebbf11560b2c5be9a}, result=4be26bc400d3c}

25

নতুন জিসন লিবের জন্য আপডেট:
আপনি এখন নেস্টেড জসনকে সরাসরি ম্যাপে পার্স করতে পারেন তবে আপনি জসনকে Map<String, Object>টাইপ করার জন্য পার্স করার চেষ্টা করার ক্ষেত্রে সচেতন হওয়া উচিত : এটি ব্যতিক্রম বাড়াবে। এটি ঠিক করার জন্য, ফলাফলটি LinkedTreeMapটাইপ হিসাবে ঘোষণা করুন । নীচে উদাহরণ:

String nestedJSON = "{"id":"1","message":"web_didload","content":{"success":1}};
Gson gson = new Gson();
LinkedTreeMap result = gson.fromJson(nestedJSON , LinkedTreeMap.class);

আমি কোথা থেকে লিংকডট্রিম্যাপটি আমদানি করব? আমি এটি জিসন কোডে খুঁজে পাচ্ছি না।
হেল্পমিস্ট্যাকওভারফ্লোমাইঅনলি হপ

আমার মনে আছে, লিংকডট্রিম্যাপটি নতুন জিসন লাইব-এ সংজ্ঞায়িত করা হয়েছে। আপনি এখানে চেক করতে পারেন: কোড. google.com/p/google-gson/source/browse/trunk/gson/src/main/…
হোয়াং

1
আমার জন্য এটি কাজ করে Map<String,Object> result = gson.fromJson(json , Map.class);। জিএসন ২.6.২ ব্যবহার করে।
ফেরান মেলিনঞ্চ

12

আমার ঠিক একই প্রশ্ন ছিল এবং এখানেই শেষ হয়েছিল। আমার একটি ভিন্ন পদ্ধতি ছিল যা দেখতে খুব সহজ বলে মনে হচ্ছে (জিএসএসের আরও নতুন সংস্করণ?)।

    Gson gson = new Gson();
    Map jsonObject = (Map) gson.fromJson(data, Object.class);

নিম্নলিখিত json সহ

{
  "map-00": {
    "array-00": [
      "entry-00",
      "entry-01"
     ],
     "value": "entry-02"
   }
}

পরবর্তী

    Map map00 = (Map) jsonObject.get("map-00");
    List array00 = (List) map00.get("array-00");
    String value = (String) map00.get("value");
    for (int i = 0; i < array00.size(); i++) {
        System.out.println("map-00.array-00[" + i + "]= " + array00.get(i));
    }
    System.out.println("map-00.value = " + value);

আউটপুট

map-00.array-00[0]= entry-00
map-00.array-00[1]= entry-01
map-00.value = entry-02

আপনার jsonObject নেভিগেট করার সময় আপনি উদাহরণস্বরূপ ব্যবহার করে চেক করতে পারেন। কিছুটা এইরকম

Map json = gson.fromJson(data, Object.class);
if(json.get("field") instanceof Map) {
  Map field = (Map)json.get("field");
} else if (json.get("field") instanceof List) {
  List field = (List)json.get("field");
} ...

এটি আমার পক্ষে কাজ করে, সুতরাং এটি অবশ্যই আপনার জন্য কাজ করবে ;-)


6

নীচে gson 2.8.0 থেকে সমর্থিত

public static Type getMapType(Class keyType, Class valueType){
    return TypeToken.getParameterized(HashMap.class, keyType, valueType).getType();
}

public static  <K,V> HashMap<K,V> fromMap(String json, Class<K> keyType, Class<V> valueType){
    return gson.fromJson(json, getMapType(keyType,valueType));
}

3

এটি চেষ্টা করুন, এটি কাজ করবে। আমি এটি ব্যবহার করেছিলাম হ্যাশটেবলের

public static Hashtable<Integer, KioskStatusResource> parseModifued(String json) {
    JsonObject object = (JsonObject) new com.google.gson.JsonParser().parse(json);
    Set<Map.Entry<String, JsonElement>> set = object.entrySet();
    Iterator<Map.Entry<String, JsonElement>> iterator = set.iterator();

    Hashtable<Integer, KioskStatusResource> map = new Hashtable<Integer, KioskStatusResource>();

    while (iterator.hasNext()) {
        Map.Entry<String, JsonElement> entry = iterator.next();

        Integer key = Integer.parseInt(entry.getKey());
        KioskStatusResource value = new Gson().fromJson(entry.getValue(), KioskStatusResource.class);

        if (value != null) {
            map.put(key, value);
        }

    }
    return map;
}

আপনার ক্লাস এবং পূর্ণসংখ্যায় কিওস্কাট্যাটাস রিসোর্স প্রতিস্থাপন করুন আপনার কী শ্রেণিতে ।


এটি আমার জন্য কাজ করেছে হ্যাশম্যাপ একটি লিঙ্কডট্রিম্যাপ ব্যতিক্রম ছুঁড়ে দেওয়ার পরে।
newfivefour

2

আমি যা ব্যবহার করছি তা এখানে:

public static HashMap<String, Object> parse(String json) {
    JsonObject object = (JsonObject) parser.parse(json);
    Set<Map.Entry<String, JsonElement>> set = object.entrySet();
    Iterator<Map.Entry<String, JsonElement>> iterator = set.iterator();
    HashMap<String, Object> map = new HashMap<String, Object>();
    while (iterator.hasNext()) {
        Map.Entry<String, JsonElement> entry = iterator.next();
        String key = entry.getKey();
        JsonElement value = entry.getValue();
        if (!value.isJsonPrimitive()) {
            map.put(key, parse(value.toString()));
        } else {
            map.put(key, value.getAsString());
        }
    }
    return map;
}

2

এখানে একটি ওয়ান-লাইনার এটি করবে:

HashMap<String, Object> myMap =
   gson.fromJson(yourJson, new TypeToken<HashMap<String, Object>>(){}.getType());

হ্যাঁ এটি একটি লাইন তবে মনে রাখবেন যে new TypeToken<HashMap<String, Object>>(){}একটি নতুন ইনলাইন সাব-ক্লাস তৈরি করবে এবং সমস্ত লিটারগুলি একটি সতর্কতা উত্থাপন করবে কমপক্ষে আমার ধারণা
মার্টিন মেসার

1

আমি একটি কাস্টম জসনডিসারিয়ালাইজারের সাথে একই রকম সমস্যা কাটিয়েছি। আমি এটিকে কিছুটা জেনেরিক করার চেষ্টা করেছি কিন্তু এখনও পর্যাপ্ত নয়। যদিও এটি আমার প্রয়োজন অনুসারে এটি একটি সমাধান।

সবার আগে আপনাকে মানচিত্রের অবজেক্টগুলির জন্য একটি নতুন জসনডিজারিয়ালার বাস্তবায়ন করতে হবে।

public class MapDeserializer<T, U> implements JsonDeserializer<Map<T, U>>

এবং ডিসরিয়ালাইজ পদ্ধতিটি এর সাথে মিল দেখায়:

public Map<T, U> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
        throws JsonParseException {

        if (!json.isJsonObject()) {
            return null;
        }

        JsonObject jsonObject = json.getAsJsonObject();
        Set<Entry<String, JsonElement>> jsonEntrySet = jsonObject.entrySet();
        Map<T, U> deserializedMap = new HashMap<T, U>();

        for (Entry<java.lang.String, JsonElement> entry : jsonEntrySet) {
            try {
                U value = context.deserialize(entry.getValue(), getMyType());
                deserializedMap.put((T) entry.getKey(), value);
            } catch (Exception ex) {
                logger.info("Could not deserialize map.", ex);
            }
        }

        return deserializedMap;
    }

এই সমাধানটির সাথে মিল হ'ল আমার মানচিত্রের কীটি সর্বদা "স্ট্রিং" টাইপের থাকে। তবে কিছু জিনিস জেনে কেউ এটিকে জেনেরিক করে তুলতে পারে। তদ্ব্যতীত, আমার বলতে হবে, মানটির শ্রেণি কনস্ট্রাক্টরে পাস করা উচিত। সুতরাং getMyType()আমার কোডের পদ্ধতিটি মানচিত্রের মানগুলির ধরণটি দেয় যা কনস্ট্রাক্টরে পাস হয়েছিল।

আপনি এই পোস্টটি উল্লেখ করতে পারেন আমি কীভাবে জিসনের জন্য একটি কাস্টম জেএসওএন ডিজিজারাইজার লিখব? যাতে কাস্টম ডিসরিওলাইজারগুলি সম্পর্কে আরও জানার জন্য।


1

পরিবর্তে আপনি এই শ্রেণিটি ব্যবহার করতে পারেন :) (এমনকি তালিকা, নেস্টেড তালিকা এবং জসন এমনকি পরিচালনা করে)

public class Utility {

    public static Map<String, Object> jsonToMap(Object json) throws JSONException {

        if(json instanceof JSONObject)
            return _jsonToMap_((JSONObject)json) ;

        else if (json instanceof String)
        {
            JSONObject jsonObject = new JSONObject((String)json) ;
            return _jsonToMap_(jsonObject) ;
        }
        return null ;
    }


   private static Map<String, Object> _jsonToMap_(JSONObject json) throws JSONException {
        Map<String, Object> retMap = new HashMap<String, Object>();

        if(json != JSONObject.NULL) {
            retMap = toMap(json);
        }
        return retMap;
    }


    private static Map<String, Object> toMap(JSONObject object) throws JSONException {
        Map<String, Object> map = new HashMap<String, Object>();

        Iterator<String> keysItr = object.keys();
        while(keysItr.hasNext()) {
            String key = keysItr.next();
            Object value = object.get(key);

            if(value instanceof JSONArray) {
                value = toList((JSONArray) value);
            }

            else if(value instanceof JSONObject) {
                value = toMap((JSONObject) value);
            }
            map.put(key, value);
        }
        return map;
    }


    public static List<Object> toList(JSONArray array) throws JSONException {
        List<Object> list = new ArrayList<Object>();
        for(int i = 0; i < array.length(); i++) {
            Object value = array.get(i);
            if(value instanceof JSONArray) {
                value = toList((JSONArray) value);
            }

            else if(value instanceof JSONObject) {
                value = toMap((JSONObject) value);
            }
            list.add(value);
        }
        return list;
    }
}

আপনার JSON স্ট্রিংকে হ্যাশম্যাপে রূপান্তর করতে এটি ব্যবহার করুন:

HashMap<String, Object> hashMap = new HashMap<>(Utility.jsonToMap(response)) ;

0

এটি সম্পূর্ণ উত্তরের চেয়ে কেভিন দোলানের উত্তরের আরও সংযোজন , তবে নম্বর থেকে টাইপটি বের করতে আমার সমস্যা হয়েছিল। এটি আমার সমাধান:

private Object handlePrimitive(JsonPrimitive json) {
  if(json.isBoolean()) {
    return json.getAsBoolean();
  } else if(json.isString())
    return json.getAsString();
  }

  Number num = element.getAsNumber();

  if(num instanceof Integer){
    map.put(fieldName, num.intValue());
  } else if(num instanceof Long){
    map.put(fieldName, num.longValue());
  } else if(num instanceof Float){
    map.put(fieldName, num.floatValue());
  } else {    // Double
     map.put(fieldName, num.doubleValue());
  }
}

-1
 HashMap<String, String> jsonToMap(String JsonDetectionString) throws JSONException {

    HashMap<String, String> map = new HashMap<String, String>();
    Gson gson = new Gson();

    map = (HashMap<String, String>) gson.fromJson(JsonDetectionString, map.getClass());

    return map;

}

-3

JSONObject সাধারণত HashMapতথ্য সংরক্ষণের জন্য অভ্যন্তরীণভাবে ব্যবহার করে। সুতরাং, আপনি এটি আপনার কোডে মানচিত্র হিসাবে ব্যবহার করতে পারেন।

উদাহরণ,

JSONObject obj = JSONObject.fromObject(strRepresentation);
Iterator i = obj.entrySet().iterator();
while (i.hasNext()) {
   Map.Entry e = (Map.Entry)i.next();
   System.out.println("Key: " + e.getKey());
   System.out.println("Value: " + e.getValue());
}

12
এটি জসন-লিব থেকে এসেছে, জিএসন নয়!
আম্মার

-3

আমি এই কোডটি ব্যবহার করেছি:

Gson gson = new Gson();
HashMap<String, Object> fields = gson.fromJson(json, HashMap.class);

এটি আমাকে চেক না করা রূপান্তর সতর্কতা দেয়।
লাইন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.