我有以下JSON:
{
"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>中。例如:
map.put(1,"3.0");
map.put(2, "abc");当我尝试在线创建POJO时,工具会生成50个对应于整数值计数的类,我不想创建50个POJO类。
请帮帮忙。
发布于 2017-05-08 19:49:25
尝尝这个
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();
}发布于 2017-05-11 22:32:47
你有没有考虑过简单的Map<K,V>来让它动态化?例如,映射可能如下所示:
final class Response {
@JsonAdapter(SpecialMapTypeAdapterFactory.class)
final Map<Integer, Object> custom = null;
}请注意custom字段的声明方式,特别是注释内容。前者使您的映射完全动态,摆脱了无数无用的映射;后者定义了一个特殊的类型适配器+工厂,负责反序列化策略:
下面的类型适配器工厂是完全动态的,但它是让它工作的一个很好的报酬。我假设您只有对(由两个字段映射支持)和字符串(由一个字段映射支持,其中值应该在反序列化过程中“解开”,并在序列化过程中“包装”回来)。
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);
}
}
}final class Pair {
@SerializedName("NAME")
final String name = null;
@SerializedName("VALUE")
final String value = null;
@Override
public String toString() {
return name + "=>" + value;
}
}把所有这些放在一起:
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”}
只是不要相信自动映射生成器,因为由于几个原因,它们并不总是有效的。
https://stackoverflow.com/questions/43846710
复制相似问题