首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用Map<Integer、Object>将JSON数据映射到自定义类型

如何使用Map<Integer、Object>将JSON数据映射到自定义类型
EN

Stack Overflow用户
提问于 2017-05-08 19:39:24
回答 2查看 808关注 0票数 0

我有以下JSON:

代码语言:javascript
复制
{
    "custom": {
        "1": {
            "v": "3.0"
        },
        "2": {
            "NAME": "YYYYYYY",
            "VALUE": "200"
        },
        "3": {
            "NAME": "YYYYYYY",
            "VALUE": "200"
        },
        "4": {
            "NAME": "YYYYYYY",
            "VALUE": "200"
        },

        "7": {
            "NAME": "XXXXXX",
            "VALUE": "100"
        },

        "26": {
            "NAME": "YYYYYYY",
            "VALUE": "200"
        },
        "27": {
            "NAME": "YYYYYYY",
            "VALUE": "200"
        },
        "28": {
            "NAME": "YYYYYYY",
            "VALUE": "200"
        },
        "29": {
            "NAME": "YYYYYYY",
            "VALUE": "200"
        }  
        }
}

我需要解析上面的JSON并将数据存储到HashMap<Integer,Object>中。例如:

代码语言:javascript
复制
map.put(1,"3.0");
map.put(2, "abc");

当我尝试在线创建POJO时,工具会生成50个对应于整数值计数的类,我不想创建50个POJO类。

请帮帮忙。

EN

回答 2

Stack Overflow用户

发布于 2017-05-08 19:49:25

尝尝这个

代码语言:javascript
复制
JSONObject jsonObject = null;
        try {
            jsonObject = new JSONObject(jsonString);

            jsonObject = jsonObject.getJSONObject("custom");
            Iterator<String> iter = jsonObject.keys();
            while (iter.hasNext()){
                String key = iter.next();
                JSONObject jsonObject1 = jsonObject.getJSONObject(key);
                ModelClass model = new ModelClass();
                if(jsonObject1.has("name"))
                model.setName(jsonObject1.getString("name"));
                if(jsonObject1.has("value"))
                model.setValue(jsonObject1.getString("value"));
                map.put(Integer.parseInt(key),model);

            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
票数 1
EN

Stack Overflow用户

发布于 2017-05-11 22:32:47

你有没有考虑过简单的Map<K,V>来让它动态化?例如,映射可能如下所示:

代码语言:javascript
复制
final class Response {

    @JsonAdapter(SpecialMapTypeAdapterFactory.class)
    final Map<Integer, Object> custom = null;

}

请注意custom字段的声明方式,特别是注释内容。前者使您的映射完全动态,摆脱了无数无用的映射;后者定义了一个特殊的类型适配器+工厂,负责反序列化策略:

下面的类型适配器工厂是完全动态的,但它是让它工作的一个很好的报酬。我假设您只有对(由两个字段映射支持)和字符串(由一个字段映射支持,其中值应该在反序列化过程中“解开”,并在序列化过程中“包装”回来)。

代码语言:javascript
复制
final class SpecialMapTypeAdapterFactory
        implements TypeAdapterFactory {

    // This is a holder for "wrapped" strings
    private static final class Single {

        @SuppressWarnings("unused")
        final String v;

        private Single(final String v) {
            this.v = v;
        }

    }

    private SpecialMapTypeAdapterFactory() {
    }

    @Override
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
        // Returning the custom type adapter that's now aware of the current Gson instance type adapters
        // (no need to lookup for a type adapter using gson.fromJson over and over)
        @SuppressWarnings("unchecked")
        final TypeAdapter<T> typeAdapter = (TypeAdapter<T>) new SpecialMapTypeAdapter(
                gson.getAdapter(JsonElement.class),
                gson.getAdapter(Single.class),
                gson.getAdapter(Pair.class)
        );
        return typeAdapter.nullSafe();
    }

    private static final class SpecialMapTypeAdapter
            extends TypeAdapter<Map<Integer, Object>> {

        private final TypeAdapter<JsonElement> jsonElementTypeAdapter;
        private final TypeAdapter<Single> singleTypeAdapter;
        private final TypeAdapter<Pair> entryTypeAdapter;

        private SpecialMapTypeAdapter(final TypeAdapter<JsonElement> jsonElementTypeAdapter, final TypeAdapter<Single> singleTypeAdapter,
                final TypeAdapter<Pair> entryTypeAdapter) {
            this.jsonElementTypeAdapter = jsonElementTypeAdapter;
            this.singleTypeAdapter = singleTypeAdapter;
            this.entryTypeAdapter = entryTypeAdapter;
        }

        // write will work too
        @Override
        @SuppressWarnings("resource")
        public void write(final JsonWriter out, final Map<Integer, Object> map)
                throws IOException {
            out.beginObject();
            for ( final Entry<Integer, Object> e : map.entrySet() ) {
                out.name(String.valueOf(e.getKey()));
                final Object value = e.getValue();
                if ( value == null ) {
                    out.nullValue();
                } else if ( value instanceof String ) {
                    singleTypeAdapter.write(out, new Single((String) value));
                } else if ( value instanceof Pair ) {
                    entryTypeAdapter.write(out, (Pair) value);
                } else {
                    throw new IllegalArgumentException("Cannot write " + value);
                }
            }
            out.endObject();
        }

        @Override
        public Map<Integer, Object> read(final JsonReader in)
                throws IOException {
            final Map<Integer, Object> map = new LinkedHashMap<>();
            in.beginObject();
            while ( in.hasNext() ) {
                final int key = parseInt(in.nextName());
                final Object value = parseValue((JsonObject) jsonElementTypeAdapter.read(in));
                map.put(key, value);
            }
            in.endObject();
            return map;
        }

        // This method attempts to analyze weakly the content of the given JsonObject respecting its properties
        // Thus either a String is returned or a Pair
        private Object parseValue(final JsonObject jsonObject)
                throws MalformedJsonException {
            if ( jsonObject.has("v") ) {
                return singleTypeAdapter.fromJsonTree(jsonObject).v;
            }
            if ( jsonObject.has("NAME") && jsonObject.has("VALUE") ) {
                return entryTypeAdapter.fromJsonTree(jsonObject);
            }
            throw new MalformedJsonException("Cannot parse " + jsonObject);
        }

    }

}
代码语言:javascript
复制
final class Pair {

    @SerializedName("NAME")
    final String name = null;

    @SerializedName("VALUE")
    final String value = null;

    @Override
    public String toString() {
        return name + "=>" + value;
    }

}

把所有这些放在一起:

代码语言:javascript
复制
private static final Gson gson = new Gson();

public static void main(final String... args)
        throws IOException {
    try ( final JsonReader jsonReader = getPackageResourceJsonReader(Q43846710.class, "dynamic.json") ) {
        final Response response = gson.fromJson(jsonReader, Response.class);
        for ( final Map.Entry<Integer, Object> e : response.custom.entrySet() ) {
            final Integer key = e.getKey();
            final Object value = e.getValue();
            System.out.println(key + " is " + value.getClass().getSimpleName() + ": " + value);
        }
        System.out.println(gson.toJson(response));
    }
}

输出:

1为字符串: 3.0

2是配对: YYYYYYY=>200

3是配对: YYYYYYY=>200

4是配对: YYYYYYY=>200

7是配对: XXXXXX=>100

26是对: YYYYYYY=>200

27是对: YYYYYYY=>200

28是对: YYYYYYY=>200

29是对: YYYYYYY=>200

{"custom":{"1":{"v":"3.0"},"2":{"NAME":"YYYYYYY","VALUE":"200"},"3":{"NAME":"YYYYYYY","VALUE":"200"},"4":{"NAME":"YYYYYYY","VALUE":"200"},"7":{"NAME":"XXXXXX","VALUE":"100"},"26":{"NAME":"YYYYYYY","VALUE":"200"},"27":{"NAME":"YYYYYYY","VALUE":"200"},"28":{"NAME":"YYYYYYY","VALUE":"200"},"29":{"NAME":"YYYYYYY",“VALUE”:“200”}

只是不要相信自动映射生成器,因为由于几个原因,它们并不总是有效的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43846710

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档