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

如何映射/组JSON属性的前缀与Jackson对象列表?

任繁
2023-03-14

我有JSON响应:

{
  "part1.id": "1",  
  "part1.name": "Name1",                 
  "part2.id": "2",                
  "part2.name": "Name2"
}

1个用户的POJO/DTO类:

public class User {

  private String id;
  private String name;

  // set/get
}

和类的整个反应:

public class UsersResponse {

  private List<User> users;

  // set/get
}

我可以在Map中检索值,然后在代码中手动解析/Map,就像Jackson JSON Map键一样,作为包含对象的属性

还有@JsonAlias用于多个命名变化,但它映射到一个对象。

是否有其他方法可以将提供的前缀的JSON值映射/分组到列表中?

共有1个答案

段干英杰
2023-03-14

没有已经实现的注释允许通过配置来完成。您需要实现反序列化器。反序列化器的简单版本如下:

class UsersResponseDeserializer extends JsonDeserializer<UsersResponse> {

    private Pattern propertyPattern = Pattern.compile("^part(\\d+)\\.(.+)$");

    @Override
    public UsersResponse deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        Integer lastIndex = null;
        String lastName = null;
        Map<Integer, Map<String, String>> users = new LinkedHashMap<>();
        while (p.currentToken() != null) {
            switch (p.currentToken()) {
                case FIELD_NAME:
                    String name = p.getText();
                    Matcher matcher = propertyPattern.matcher(name);
                    if (matcher.matches()) {
                        lastIndex = Integer.parseInt(matcher.group(1));
                        lastName = matcher.group(2);
                    }
                    break;
                case VALUE_STRING:
                    if (lastIndex != null && lastName != null) {
                        Map<String, String> user = users.computeIfAbsent(lastIndex, k -> new HashMap<>());
                        user.put(lastName, p.getValueAsString());
                        lastIndex = null;
                        lastName = null;
                    }
                    break;
                default:
                    break;
            }
            p.nextToken();
        }

        UsersResponse response = new UsersResponse();
        response.setUsers(users);

        return response;
    }
}

我更改了一点UsersResponse,如下所示:

@JsonDeserialize(using = UsersResponseDeserializer.class)
class UsersResponse {

    private Map<Integer, Map<String, String>> users;

    public Map<Integer, Map<String, String>> getUsers() {
        return users;
    }

    public void setUsers(Map<Integer, Map<String, String>> users) {
        this.users = users;
    }

    @Override
    public String toString() {
        return "UsersResponse{" +
                "users=" + users +
                '}';
    }
}

用法示例:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.type.CollectionLikeType;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("path to json").getAbsoluteFile();


        ObjectMapper mapper = new ObjectMapper();
        UsersResponse data = mapper.readValue(jsonFile, UsersResponse.class);
        System.out.println(data);
        CollectionLikeType usersListType = mapper.getTypeFactory().constructCollectionLikeType(List.class, User.class);
        List<User> users = mapper.convertValue(data.getUsers().values(), usersListType);
        System.out.println(users);
    }
}

Abobe应用程序用于给定的JSON

{
  "part1.id": "1",
  "part1.name": "Name1",
  "part2.id": "2",
  "part2.name": "Name2",
  "part33.id": "33",
  "part33.name": "Name33"
}

印刷品:

UsersResponse{users={1={name=Name1, id=1}, 2={name=Name2, id=2}, 33={name=Name33, id=33}}}
[User{id='1', name='Name1'}, User{id='2', name='Name2'}, User{id='33', name='Name33'}]

在反序列化程序中,我使用了Map

 类似资料:
  • 问题内容: 给定这样的结构: 是否可以将其映射到: 这样,您最终获得的实例的属性分别设置为和? 问题答案: 我坚信将您的POJO与外部化分开。将您的JSON读取到Map中,然后像这样构建您的Container / ScoreKeeper对象(对于任何错别字都为apols):

  • 假设我有这样的物体 我正在使用RestTemboard类从URL中获取json,如下所示: 之后,我想使用jackson对象映射器将json字符串转换为一个对象 将实体类作为第二个参数传递 问题是我应该如何编写ExampleJson实体来处理get-Showed json?我试过这样上课,但似乎不管用。 我得到了这样一个例外:

  • 我使用http://jsonlint.com来验证JSON是否有效。因此,我要么需要更改JSON或代码,要么可能两者都需要。有什么想法吗?

  • 当遍历ACROD时,有一个列表,并希望将该列表中的第一个对象映射到我的域对象。 @mapping(source=“insurancesvcrqs[0].policyquoteinqrqsaddrqsandpolicyquoteinqrqs[0].productues[0].generalpartyinfo.nameinfos[0].commlname.commericalname”,target=

  • 我需要反序列化以下json: 将它的< code>id属性设置为< code>foo_id json属性。 我需要在自定义反序列化程序中执行此操作。实现这一点最简单的方法是什么? 我想以某种方式将json“转换”为 然后将此委托给杰克逊。 在本例中,对象的类型为Foo,但其他对象可能不属于此类。另外,在本例中,json是一个数字,但如果它也是一个字符串,我希望支持。所以,我需要一种通用的方法来做到

  • 问题内容: 我有一个用表声明的方式映射到表的类,并且我想从此类中“发现”表属性,列,名称,关系: 因此,现在我的目标是从“ Ship”类中从另一段代码中获取表列及其属性。我想我可以使用工具来处理它,但是SQLAlchemy API是否提供任何方法? 问题答案: 您可以从Table对象获取所需的信息: 将为您提供列信息 将列出外键 ,您可能会发现其他有用的属性