当前位置: 首页 > 知识库问答 >
问题:

如何用Gson序列化一个特殊的json(对象的内容)

巫马安怡
2023-03-14
{
    "age": 26,
    "email": "norman@futurestud.io",
    "isDeveloper": true,
    "name": "Norman",

    "userAddress": {
        "city": "Magdeburg",
        "country": "Germany",
        "houseNumber": "42A",
        "street": "Main Street"
    }
}
{
    "age": 26,
    "email": "norman@futurestud.io",
    "isDeveloper": true,
    "name": "Norman",
    "city": "Magdeburg",
    "country": "Germany",
    "houseNumber": "42A",
    "street": "Main Street"
}

我尝试使用以下代码,但错误:

@Expose
private final String age;
...
@Expose
@JsonAdapter(UserAddressSerializer.class)
private final UserAddress userAddress;
...


public class UserAddressSerializer implements JsonSerializer<UserAddress > {

    @Override
    public JsonElement serialize(UserAddress src, Type typeOfSrc, JsonSerializationContext context) {
        JsonObject result = new JsonObject();
        result.add("name", new JsonPrimitive(src.getName()));
        result.add("city", new JsonPrimitive(src.getCity()));
        result.add("country", new JsonPrimitive(src.getCountry()));
        result.add("houseNumber", new JsonPrimitive(src.getHouseNumber()));
        result.add("street", new JsonPrimitive(src.getStreet()));
        return result;
    }

}

共有1个答案

燕刚捷
2023-03-14

JSON树就是您正在寻找的。但这里至少有一个警告是在不同对象之间共享相同名称的属性名称。

假设您有以下数据类:

final class User {

    final String email;
    final String name;
    final int age;
    final boolean isDeveloper;

    User(final String email, final int age, final String name, final boolean isDeveloper) {
        this.age = age;
        this.email = email;
        this.isDeveloper = isDeveloper;
        this.name = name;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("email", email)
                .add("name", name)
                .add("age", age)
                .add("isDeveloper", isDeveloper)
                .toString();
    }

}
final class UserAddress {

    final String country;
    final String city;
    final String street;
    final String houseNumber;

    UserAddress(final String country, final String city, final String street, final String houseNumber) {
        this.country = country;
        this.city = city;
        this.street = street;
        this.houseNumber = houseNumber;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("country", country)
                .add("city", city)
                .add("street", street)
                .add("houseNumber", houseNumber)
                .toString();
    }

}

现在,您可以使用实用工具方法将多个对象序列化为单个JSONObject实例。此外,您可以轻松地拥有一个反序列化计数器部件,它可以从JSONObject实例反序列化多个对象。例如:

final class JsonObjects {

    private JsonObjects() {
    }

    @SafeVarargs
    static JsonObject combine(final Gson gson, final Map.Entry<Object, ? extends Type>... objectAndTypeEntries) {
        return Stream.of(objectAndTypeEntries)
                // Each element should be serialized to a JsonElement
                .map(e -> gson.toJsonTree(e.getKey(), e.getValue()))
                // That must be a JSON object
                .map(JsonElement::getAsJsonObject)
                // And now we can collect a stream of JsonObject instances into a super-object
                .collect(Collector.of(
                        JsonObject::new, // We'll collect into a new JsonObject instance, this is the accumulator
                        JsonObjects::mergeInto, // Merge each consecutive JsonObject instance into the accumulator
                        JsonObjects::mergeInto, // Or even combine multiple accumulators
                        Function.identity() // And just return the accumulator
                ));
    }

    static List<?> split(final Gson gson, final JsonObject jsonObject, final Type... types) {
        return Stream.of(types)
                // Each element should be deserialized from the JsonObject by a type
                .map(type -> gson.fromJson(jsonObject, type))
                // And just collect all the deserialized objects to a list
                .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
    }

    private static JsonObject mergeInto(final JsonObject to, final JsonObject from) {
        for ( final Map.Entry<String, JsonElement> e : from.entrySet() ) {
            to.add(e.getKey(), e.getValue());
        }
        return to;
    }

}
final User beforeUser = new User("norman@localhost", 26, "Norman", true);
System.out.println("BEFORE User: " + beforeUser);
final UserAddress beforeUserAddress = new UserAddress("Germany", "Magdeburg", "Main Street", "42A");
System.out.println("BEFORE User address: " + beforeUserAddress);
final JsonObject jsonObject = JsonObjects.combine(
        gson,
        new AbstractMap.SimpleImmutableEntry<>(beforeUser, User.class),
        new AbstractMap.SimpleImmutableEntry<>(beforeUserAddress, UserAddress.class)
);
System.out.println("JSON: " + jsonObject);
final List<?> objects = JsonObjects.split(gson, jsonObject, User.class, UserAddress.class);
final User afterUser = (User) objects.get(0);
System.out.println("AFTER User: " + afterUser);
final UserAddress afterUserAddress = (UserAddress) objects.get(1);
System.out.println("AFTER User address: " + afterUserAddress);
BEFORE User: User{email=norman@localhost, name=Norman, age=26, isDeveloper=true}
BEFORE User address: UserAddress{country=Germany, city=Magdeburg, street=Main Street, houseNumber=42A}
JSON: {"email":"norman@localhost","name":"Norman","age":26,"isDeveloper":true,"country":"Germany","city":"Magdeburg","street":"Main Street","houseNumber":"42A"}
AFTER User: User{email=norman@localhost, name=Norman, age=26, isDeveloper=true}
AFTER User address: UserAddress{country=Germany, city=Magdeburg, street=Main Street, houseNumber=42A}
 类似资料:
  • 打完电话后 我只填充了的和。列表始终保持。我怎么才能修好这个?

  • 问题内容: 我有以下JSON字符串: 我需要将值存储在单独的字符串中。 这是我到目前为止所拥有的,但这只是为我提供了整个JSON字符串,而不是特定的imgurl字段。 是JSON字符串。这是我的数据类: 问题答案: 解析这种简单的结构时,不需要专用的类。 解决方案1: 要使用gson从字符串中获取imgurURL,可以执行以下操作: 这使用原始解析到JsonObject中。 解决方案2: 另外,您

  • 这是我目前所拥有的,但这只给了我整个JSON字符串,而不是特定的imgurl字段。 是JSON字符串。下面是我的数据类:

  • 问题内容: 我在尝试使用Gson库反序列化对象的JSON数组时遇到问题。 JSON数组的示例: 你怎么看?反序列化此类JSON响应的正确Java代码是什么? 问题答案: 要反序列化JSONArray,您需要使用TypeToken。您可以从GSON用户指南中了解更多信息。示例代码: 如果您有JSONArray,则可以使用

  • 这个json对象有时可能非常非常大,我想用GSON解析它,但我不太明白我的java对象的格式应该如何解析它们。 真正的肉在键中,第二个键是JSONArray。每个索引包含一个对象,每个对象可以包含一个键,该键也是一个json数组,在某些情况下可以包含json数组。 我有所有这些的模型,有不同的解析范式,但没有GSON的模型。由于内存限制,我现在需要使用GSON

  • 问题内容: 我想使用套接字(在开发远程PC时)从Android客户端向Java服务器发送2个对象。 当然我知道上面的方法是行不通的,因为它可以提供。所以现在我想知道如何使用Gson库对对象进行序列化和反序列化。提前致谢。 问题答案: gson可以在任何平台上与Java一起使用-不仅限于Android。 使用gson序列化单个对象: 使用gson反序列化为单个对象。 从示例中可以看到,gson非常神