Gson:如果属性名称未修复,如何将内部JSON对象反序列化为地图?

时间:2017-06-13 02:19:36

标签: gson

我的客户端检索JSON内容如下:

{
    "table": "tablename",
    "update": 1495104575669,
    "rows": [
        {"column5": 11, "column6": "yyy"},
        {"column3": 22, "column4": "zzz"}
    ]
}

rows数组内容中,密钥未修复。我想检索密钥和值,并使用Gson 2.8.x保存到Map

如何将Gson配置为仅用于反序列化?

这是我的想法:

public class Dataset {

    private String table;
    private long update;
    private List<Rows>> lists; <-- little confused here.
       or private List<HashMap<String,Object> lists 

    Setter/Getter
}
public class Rows {

    private HashMap<String, Object> map;

    ....
}

Dataset k = gson.fromJson(jsonStr, Dataset.class);
log.info(k.getRows().size()); <-- I got two null object

感谢。

1 个答案:

答案 0 :(得分:1)

Gson不支持开箱即用。如果您可以修改属性名称,那就太好了。如果没有,那么您可以选择一些可能对您有帮助的选项。

  • 如果属性名称已修复,只需将Dataset.lists字段重命名为Dataset.rowsrows
  • 如果事先知道可能的名称集,建议Gson使用@SerializedName选择其他名称。
  • 如果可能的名称集确实未知并且将来可能会更改,您可能希望尝试使用自定义TypeAdapter(流模式;需要更少的内存,但更难使用)或在JsonDeserializer注册的自定义GsonBuilder(对象模式;需要更多内存来存储中间树视图,但它易于使用)。

对于选项#2,您只需添加名称替代品的名称:

@SerializedName(value = "lists", alternate = "rows")
final List<Map<String, Object>> lists;

对于选项#3,绑定试图动态检测名称的下游List<Map<String, Object>>类型适配器。请注意,为简单起见,我省略了Rows类反序列化策略(我相信您可能希望删除Rows类,而不是简单Map<String, Object>(另请注意:使用Map ,尽量不指定集合实现 - 哈希映射是无序的,但是告诉Gson你要处理Map会让它选择一个有序的地图,如LinkedTreeMap(Gson internals)或LinkedHashMap对数据集可能很重要))。

// Type tokens are immutable and can be declared constants

private static final TypeToken<String> stringTypeToken = new TypeToken<String>() {
};

private static final TypeToken<Long> longTypeToken = new TypeToken<Long>() {
};

private static final TypeToken<List<Map<String, Object>>> stringToObjectMapListTypeToken = new TypeToken<List<Map<String, Object>>>() {
};

private static final Gson gson = new GsonBuilder()
        .registerTypeAdapterFactory(new TypeAdapterFactory() {
            @Override
            public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
                if ( typeToken.getRawType() != Dataset.class ) {
                    return null;
                }
                // If the actual type token represents the Dataset class, then pick the bunch of downstream type adapters
                final TypeAdapter<String> stringTypeAdapter = gson.getDelegateAdapter(this, stringTypeToken);
                final TypeAdapter<Long> primitiveLongTypeAdapter = gson.getDelegateAdapter(this, longTypeToken);
                final TypeAdapter<List<Map<String, Object>>> stringToObjectMapListTypeAdapter = stringToObjectMapListTypeToken);
                // And compose the bunch into a single dataset type adapter
                final TypeAdapter<Dataset> datasetTypeAdapter = new TypeAdapter<Dataset>() {
                    @Override
                    public void write(final JsonWriter out, final Dataset dataset) {
                        // Omitted for brevity
                        throw new UnsupportedOperationException();
                    }

                    @Override
                    public Dataset read(final JsonReader in)
                            throws IOException {
                        in.beginObject();
                        String table = null;
                        long update = 0;
                        List<Map<String, Object>> lists = null;
                        while ( in.hasNext() ) {
                            final String name = in.nextName();
                            switch ( name ) {
                            case "table":
                                table = stringTypeAdapter.read(in);
                                break;
                            case "update":
                                update = primitiveLongTypeAdapter.read(in);
                                break;
                            default:
                                lists = stringToObjectMapListTypeAdapter.read(in);
                                break;
                            }
                        }
                        in.endObject();
                        return new Dataset(table, update, lists);
                    }
                }.nullSafe(); // Making the type adapter null-safe
                @SuppressWarnings("unchecked")
                final TypeAdapter<T> typeAdapter = (TypeAdapter<T>) datasetTypeAdapter;
                return typeAdapter;
            }
        })
        .create();
final Dataset dataset = gson.fromJson(jsonReader, Dataset.class);
System.out.println(dataset.lists);

上面的代码将打印出来:

  

[{column5 = 11.0,column6 = yyy},{column3 = 22.0,column4 = zzz}]

相关问题