序列化对象列表,以属性为键。

问题描述 投票:0回答:1

假设我有一个类。

public class Person {
   String name;
   Int age;
}

和一个该类的对象列表。

List<Person> people = ...

通常情况下,通过一个序列化器来运行这些对象,比如说 杰克逊Gson 会导致这样的结果。

"[{'name':'John','age':42},{'name':'Sam','age':43}]

但我想把它序列化成一个单一的json对象 每个属性都是一个包含属性的列表,就像这样。

"{'name':['John','Sam'],'age':[42,43]}"

有哪个序列化库支持这样的功能吗?

java json serialization jackson gson
1个回答
1
投票

我会创建一个 "包装器",它可以接收任意数量的人,并以一种允许它们被序列化的方式存储字段。所以在这种情况下,你会创建一系列的人员,创建一个包含这些人员的包装器,然后将其序列化。

public class PersonWrapper {

    private int[] ages;
    private String[] names;

    public PersonWrapper(Person... persons) {
        ages = new int[persons.length];
        names = new String[persons.length];

        for (int i = 0; i < persons.length; i++) {
            ages[i] = persons[i].getAge();
            names[i] = persons[i].getName();
        }
    }
}

0
投票

转变你的 List<Person> 为新对象。

class NewClass {
    List<String> name;
    List<Integer> ages;
}

然后把这个对象通过Serializer来获取。"{'name':['John','Sam'],'age':[42,43]}"


0
投票

序列化库一般不是为这样的东西而设计的.你要找的是JSON树的转换,你可以很容易地在Gson和Jackson中实现它.

这里是一个Gson的转换例子。

final class Transformations {

    private Transformations() {
    }

    static JsonObject transposeShallow(final Iterable<? extends JsonElement> inArray) {
        final JsonObject outObject = new JsonObject();
        for ( final String name : scanAllNames(inArray) ) {
            final JsonArray outSubArray = new JsonArray();
            for ( final JsonElement inJsonElement : inArray ) {
                if ( !inJsonElement.isJsonObject() ) {
                    throw new IllegalArgumentException(inJsonElement + " is not a JSON object");
                }
                outSubArray.add(inJsonElement.getAsJsonObject().get(name));
            }
            outObject.add(name, outSubArray);
        }
        return outObject;
    }

    private static Iterable<String> scanAllNames(final Iterable<? extends JsonElement> jsonArray) {
        final ImmutableSet.Builder<String> allNames = new ImmutableSet.Builder<>();
        for ( final JsonElement jsonElement : jsonArray ) {
            if ( !jsonElement.isJsonObject() ) {
                throw new IllegalArgumentException(jsonElement + " is not a JSON object");
            }
            allNames.addAll(jsonElement.getAsJsonObject().keySet());
        }
        return allNames.build();
    }

}

上面的转换可以纳入序列化过程,但这将影响你的对象的结构(例如,如何为根对象及其字段指示可转置集合?如何引入一个新的 "转置 "类型并将其纳入你的数据模型类型系统?如果必要的话,如何正确地反序列化?)。

一旦你得到一棵JSON树,你就可以在任何嵌套层次上进行转置.只要你不需要转换嵌套元素,转置根元素是最简单的方法。

private static final Type peopleType = new TypeToken<Collection<Person>>() {}.getType();

public static void main(final String... args) {
    System.out.println(gson.toJson(people, peopleType));
    System.out.println(gson.toJson(Transformations.transposeShallow(gson.toJsonTree(people, peopleType).getAsJsonArray())));
}

这就给出了。

[{"name":"John","age":42},{"name":"Sam","age":43}]
{"name":["John","Sam"],"age":[42,43]}

上面的解决方案可以适用于你代码中的几乎所有类型, 但对于构建JSON树来说,它有一个小小的惩罚. PersonWrapper 如Schred所建议的那样,可能是另一种选择,但这需要为你的所有类型提供包装器,而且一旦你的包装类发生变化,它们就需要更新。

另外,你可能也会对一些库感兴趣,如 震动 是为JSON转换而设计的(不知道在Jolt中是否可以做到)。

© www.soinside.com 2019 - 2024. All rights reserved.