如何在安卓中将 HashMap 转换为 JSON 数组?

24

我想将 HashMap 转换为 json数组,我的代码如下:

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

map.put("first", "First Value");

map.put("second", "Second Value");

我已经尝试过这个方法,但它没有起作用。是否有其他解决方案?

JSONArray mJSONArray = new JSONArray(Arrays.asList(map));

1
所以,你有一个 Map,但想要一个 Array?好的,首先进行转换,独立于JSON,然后将结果(现在是List/Array)提供给适当的JSON转换器。发布的代码不起作用 - 并且会导致编译器错误,应该包含在帖子中 - 因为没有 Arrays.asList(Map<K,V>),因为这没有普遍意义(尽管,也许你想要一个条目列表?)。也就是说,这个问题与JSON直接无关。 - user166390
@pst:谢谢,但有没有解决方案?在Android活动中创建带键值对的数组并将其转换为JSON? - Sandeep
数组没有“键=>值”。提供示例Map数据和预期的JSON数组输出。 - user166390
键值仅在集合的Map家族中可用,尝试将Map转换为String并操作String。 - subodh
5个回答

49

试一试这个,

public JSONObject (Map copyFrom) 

通过从给定的映射中复制所有名称/值映射来创建新的JSONObject。

参数 copyFrom:键为String类型,值为支持的类型的映射。

如果映射中的任何键为null,则抛出NullPointerException异常。

基本用法:

JSONObject obj=new JSONObject(yourmap);
从JSONObject中获取json数组
编辑:
JSONArray array=new JSONArray(obj.toString());

编辑:(如果发现异常,可以按@krb686在评论中提到的更改)

JSONArray array=new JSONArray("["+obj.toString()+"]");

我已经尝试过了,但没有成功。你能把代码粘贴在这里吗? - Sandeep
我不知道它应该按什么逻辑工作。我只能希望它经过了测试 - 显示输入和每个阶段的输出将使这成为一个可以接受的答案。 - user166390
1
很抱歉 @Pragnani,这不起作用了,可能以前有用过,但现在不行了。它会抛出以下错误:A JSONArray text must start with '[' at character 1在从JSONObject创建JSONArray的行上。修正方案 您需要更改为:JSONArray array=new JSONArray("[" + obj.toString() + "]");您能够进行编辑吗?谢谢。 - krb686
在Java 7、API 26 Android中,以上解决方案都无法生成有效的JSON数组输出。map.toString()函数会生成大括号{},而不是中括号[]。 - Ed J

16

从安卓API Lvl 19开始,您可以简单地执行new JSONObject(new HashMap())。但在旧的API级别上,你会得到丑陋的结果(将每个非原始值应用toString)。

我收集了JSONObject和JSONArray的方法,以便获得简化和美化的结果。您可以使用我的解决方案类:

package you.package.name;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;

public class JsonUtils
{
    public static JSONObject mapToJson(Map<?, ?> data)
    {
        JSONObject object = new JSONObject();

        for (Map.Entry<?, ?> entry : data.entrySet())
        {
            /*
             * Deviate from the original by checking that keys are non-null and
             * of the proper type. (We still defer validating the values).
             */
            String key = (String) entry.getKey();
            if (key == null)
            {
                throw new NullPointerException("key == null");
            }
            try
            {
                object.put(key, wrap(entry.getValue()));
            }
            catch (JSONException e)
            {
                e.printStackTrace();
            }
        }

        return object;
    }

    public static JSONArray collectionToJson(Collection data)
    {
        JSONArray jsonArray = new JSONArray();
        if (data != null)
        {
            for (Object aData : data)
            {
                jsonArray.put(wrap(aData));
            }
        }
        return jsonArray;
    }

    public static JSONArray arrayToJson(Object data) throws JSONException
    {
        if (!data.getClass().isArray())
        {
            throw new JSONException("Not a primitive data: " + data.getClass());
        }
        final int length = Array.getLength(data);
        JSONArray jsonArray = new JSONArray();
        for (int i = 0; i < length; ++i)
        {
            jsonArray.put(wrap(Array.get(data, i)));
        }

        return jsonArray;
    }

    private static Object wrap(Object o)
    {
        if (o == null)
        {
            return null;
        }
        if (o instanceof JSONArray || o instanceof JSONObject)
        {
            return o;
        }
        try
        {
            if (o instanceof Collection)
            {
                return collectionToJson((Collection) o);
            }
            else if (o.getClass().isArray())
            {
                return arrayToJson(o);
            }
            if (o instanceof Map)
            {
                return mapToJson((Map) o);
            }
            if (o instanceof Boolean ||
                    o instanceof Byte ||
                    o instanceof Character ||
                    o instanceof Double ||
                    o instanceof Float ||
                    o instanceof Integer ||
                    o instanceof Long ||
                    o instanceof Short ||
                    o instanceof String)
            {
                return o;
            }
            if (o.getClass().getPackage().getName().startsWith("java."))
            {
                return o.toString();
            }
        }
        catch (Exception ignored)
        {
        }
        return null;
    }
}

如果你在你的Map上应用mapToJson()方法,你可以得到这样的结果:

{
  "int": 1,
  "Integer": 2,
  "String": "a",
  "int[]": [1,2,3],
  "Integer[]": [4, 5, 6],
  "String[]": ["a","b","c"],
  "Collection": [1,2,"a"],
  "Map": {
    "b": "B",
    "c": "C",
    "a": "A"
  }
}

1
太棒了!我希望我能给这个+10分!我得查看API 19的源代码,看看他们是不是这样做的。谢谢! - bstar55
遇到了同样的问题,无法解码的字符串看起来像:{key=value, key2=value2} - Vans S

3

一个map由键值对组成,即每个条目有两个对象,而列表只有一个对象。你可以做的是提取所有Map.Entry<K,V>,然后将它们放入数组中:

Set<Map.Entry<String, String> entries = map.entrySet();
JSONArray mJSONArray = new JSONArray(entries);

另外,有时将键或值提取到集合中是很有用的:

Set<String> keys = map.keySet();
JSONArray mJSONArray = new JSONArray(keys);

或者

List<String> values = map.values();
JSONArray mJSONArray = new JSONArray(values);

注意:如果您选择使用作为条目,则无法保证顺序(keySet()方法返回一个Set)。这是因为Map接口没有指定任何顺序(除非Map恰好是SortedMap)。

2
这是最简单的方法。 只需使用
JSONArray jarray = new JSONArray(hashmapobject.toString);

1
你可以使用以下代码将map转换为JSONArray: JSONArray jarray = JSONArray.fromObject(map);

尝试这个:http://stackoverflow.com/questions/9210273/how-to-create-a-complex-json-using-hashmap-in-android - Asraful
这些类可在 JSON-Lib 库中使用。您可以在此处找到该库:http://json-lib.sourceforge.net/ - Sadeshkumar Periyasamy
@Forhad:谢谢,但我的哈希表是在我的代码中动态创建的,所以这对我来说不太合适。有没有其他选项可以在Android活动中创建键值对数组并将其转换为JSON? - Sandeep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接