首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用genson解析嵌套json?

如何使用genson解析嵌套json?
EN

Stack Overflow用户
提问于 2019-05-13 14:04:15
回答 2查看 432关注 0票数 0

我从REST中获得结果,它是一个表示用户的json对象的列表,每个用户内部都有嵌套的json对象。我的问题是嵌套属性名称与我在代码中获得的bean属性不相对应。但是它们太不合适了,所以我真的不想保留API嵌套的属性名称.

我使用Genson1.5和java 8,lombok作为我的bean。我尝试使用简单的反序列化器,然后使用转换器,但没有成功。

下面是我从API中得到的一个例子:

代码语言:javascript
复制
[
   {
      "FirstName": "Jack",
      "LastName": "Sparrow",
      "Adress": {
                   "String1": "Toulon",
                   "String2": "France",
                   "String3": "83",
                }
   },
   {
      "FirstName": "I am",
      "LastName": "Groot",
      "Adress": {
                   "String1": "Marseille",
                   "String2": "France",
                   "String3": "13",
                }
   },
]

下面是我想要作为新格式的bean:

代码语言:javascript
复制
@Data
public class User {
   private String firstName;
   private String lastName;
   private String country; //this represents String2 from the API
}

我已经尝试过这些解决方案:

  • 只需使用反序列化推荐值(错误是因为与我的bean相比没有从api获得相同的属性):
代码语言:javascript
复制
private Genson genson = new Genson();

public List<User> getUserList() {
   Response response = api.target(url)...get();
   List<User> users = genson.deserialize(response.readEntity(String.class), new GenericType<List<User>>(){});
   return users;
}
  • 使用转换器获取与我的bean相同的参数
代码语言:javascript
复制
private Genson genson = new GensonBuilder().withConverters(new UserConverter()).create();

public List<User> getUserList() {
   Response response = api.target(url)...get();
   List<User> users = this.genson.deserialize(response.readEntity(String.class), new genericType<List<User>>(){});
   return users;
}
代码语言:javascript
复制
public class UserConverter implements Converter<User> {

    public User deserialize(ObjectReader reader, Context ctx) throws Exception {
        User user = new User();
        reader.beginObject();

        while (reader.hasNext()) {
            reader.next();
            if ("FirstName".equals(reader.name())) {
                user.setFirstName(reader.valueAsString());
            } else if ("LastName".equals(reader.name())) {
                user.setLastName(reader.valueAsString());
            } else if ("Adress".equals(reader.name())) {
                reader.beginObject();
                while (reader.hasNext()) {
                    if ("String2".equals(reader.name())) {
                        user.setCountry(reader.valueAsString());
                    } else {
                        reader.skipValue();
                    }
                }
                reader.endObject();
            } else {
                reader.skipValue();
            }
        }

        reader.endObject();
        return user;
    }

    @Override
    public void serialize(User object, ObjectWriter writer, Context ctx) throws Exception {
        // TODO Auto-generated method stub

    }
}

错误是:

代码语言:javascript
复制
com.owlike.genson.JsonBindingException: Could not deserialize to type interface java.util.List
    at com.owlike.genson.Genson.deserialize(Genson.java:384)
    ...

Caused by: com.owlike.genson.stream.JsonStreamException: Illegal character at row 0 and column 660 expected } but read '{' !
    at com.owlike.genson.stream.JsonReader.newWrongTokenException(JsonReader.java:942)
    ...

Genson在http://genson.io/Documentation/UserGuide/#custom-serde给出了一个例子,但是他们将整数列表作为一个值来读取,这就是为什么我尝试了嵌套而为嵌套的json.

如果有人对如何处理我的问题有想法,非常感谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-13 19:49:27

@eugen谢谢您的回答,我尝试了@JsonProperty在我的每个bean参数上面,但不幸的是它不起作用。

然后出现了一个学院,我们在UserConverter中添加了以下内容:

代码语言:javascript
复制
private GenericType<Map<String, String>> adressMap = new GenericType<Map<String, String>>() {};

并将第二次更改为:

代码语言:javascript
复制
else if ("Adress".equals(reader.name())) {
   user.string2Value((ctx.genson.deserialize(adressMap, reader, ctx)).get("String2"));
}

这实际上是可行的。

票数 1
EN

Stack Overflow用户

发布于 2019-05-13 17:56:02

您的问题是,JSON中属性的名称与代码中的属性不同。注在您的JSON中,第一个字母是大写。

您有几个选项:-在您的JSON中重命名它们-在代码端用@JsonProperty("newname")重命名或者使用builder.rename(currentName, newName)重命名。-实现一个自定义PropertyNameResolver,它将名称解析委托给ConventionalBeanPropertyNameResolver,然后将第一个字母更改为大写。

您可以在启动时实现自定义转换器,但如果您需要对每种类型进行转换,则这将是一项相当大的工作。

我建议实现自定义名称解析器。

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

https://stackoverflow.com/questions/56114058

复制
相关文章

相似问题

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