使用Jackson从请求JSON中提取某些字段和值

使用Jackson从请求JSON中提取某些字段和值,json,spring-boot,jackson,Json,Spring Boot,Jackson,我正在寻找一种方法,只包含从接收到我的服务的JSON请求中的某些字段,然后相应地记录它们,以避免记录太多数据 要包含的字段和日志将在属性文件中配置 由于我使用Spring Boot提供服务,Jackson JARs应该已经可以使用了 由于请求JSON非常复杂,包含嵌套数组和对象作为字段,我不确定我是否可以使用Jackson实现我的要求 有没有办法使用Jackson API从输入请求JSON中仅提取某些字段及其值 基本上,我在看两个用例 1.从Json字符串中选择一个或多个元素(我打算通过配置传递

我正在寻找一种方法,只包含从接收到我的服务的JSON请求中的某些字段,然后相应地记录它们,以避免记录太多数据

要包含的字段和日志将在属性文件中配置

由于我使用Spring Boot提供服务,Jackson JARs应该已经可以使用了

由于请求JSON非常复杂,包含嵌套数组和对象作为字段,我不确定我是否可以使用Jackson实现我的要求

有没有办法使用Jackson API从输入请求JSON中仅提取某些字段及其值

基本上,我在看两个用例

1.从Json字符串中选择一个或多个元素(我打算通过配置传递),然后呈现它们

2.选择并更新一个或多个内联元素。我想在渲染元素之前屏蔽它们的值

我提供了选择元素和Json的代码,我使用了这些元素和Json,下面是我所期望的

public String getValues(String key,String jsonString){
    String fieldNodeStr =null;
    try {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.readTree(jsonString);
        JsonNode fieldNode = node.at(key);
        fieldNodeStr = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(fieldNode);
        System.out.println(fieldNodeStr);
    } catch (IOException e) {
        System.out.println("IOException:",e);
    }catch (Exception e) {
        System.out.println("Exception:",e);
    }
}   
我的Json如下所示

{
    "employeeId" : "5353",
    "salesId" : "sales005",
    "manager" : {
        "userId" : "managerUser",
        "isSuperUser" : false,
        "firstName":"manager first name",
        "lastName":"manager last name"
            },
    "administrator" : {
        "userId" : "administratorUser",
        "isSuperUser" : false,
        "firstName":"admin first name",
        "lastName":"admin last name"
    },
    "requester" : [
                    {
                            "id":"1234",
                            "demographic" : {
                                                "firstName" : "hello",
                                                "lastName" : "hai"
                                             }
                     },
                     {
                            "id":"1235",
                            "demographic" : {
                                                "firstName" : "welcome",
                                                "lastName" : "user"
                                            }
                      }
                   ]

}
我有两个问题如下

public String getValues(String key,String jsonString){
    String fieldNodeStr =null;
    try {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.readTree(jsonString);
        JsonNode fieldNode = node.at(key);
        fieldNodeStr = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(fieldNode);
        System.out.println(fieldNodeStr);
    } catch (IOException e) {
        System.out.println("IOException:",e);
    }catch (Exception e) {
        System.out.println("Exception:",e);
    }
}   
如果我通过“/manager/userId”、“/administrator/issupurer”(或“/salesId”,我就能够获得预期的值

但是,如果要获取/requester/id(或)/requester/demographic(或)/requester/demographic/lastName,我无法获取。 我得到了空值

当我分别通过“/requester/id”(或“/requester/demographic”时,我希望出现以下情况

"requester" : [
                    {
                            "id":"1234"
                     },
                     {
                            "id":"1235"
                      }
                ]


 "requester" : [
                    {
                            "demographic" : {
                                                "firstName" : "hello",
                                                "lastName" : "hai"
                                             }
                     },
                     {
                            "demographic" : {
                                                "firstName" : "welcome",
                                                "lastName" : "user"
                                            }
                      }
                   ]
除了fetch之外,我还希望在使用JsonPointer定位这些值之后,对它们进行内联更新

我的更新代码如下所示

public String findAndUpdate(String key,String jsonString,String repValue){
    String fieldNodeStr =null;
    try {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.readTree(jsonString);
        JsonNode fieldNode = node.at(key);

        //Update the value of located node to a different one
        ((ObjectNode) fieldNode).put(key,repValue);

        fieldNodeStr = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(fieldNode);
        System.out.println(fieldNodeStr);
    } catch (IOException e) {
        System.out.println("IOException:",e);
    }catch (Exception e) {
        System.out.println("Exception:",e);
    }
    return fieldNodeStr;
}
当我传递“/manager/userId”作为key的值时,我得到以下错误

17:21:24.829 [main] ERROR com.demo.jsondemo.TestClass - Exception:
java.lang.ClassCastException: com.fasterxml.jackson.databind.node.TextNode cannot be cast to com.fasterxml.jackson.databind.node.ObjectNode
    at com.demo.jsondemo.TestClass.findAndUpdate(TestClass.java:95) [classes/:na]
    at com.demo.jsondemo.TestClass.main(TestClass.java:221) [classes/:na]

Jackson的JsonView注释应该允许您使用特定视图标记某些字段/getter。像下面这样的方法应该可以奏效

public class Item {
    public static class LoggingView {}

    @JsonView(LoggingView.class)
    public int id;

    @JsonView(LoggingView.class)
    public String name;

    public byte[] data;
}
这应该允许您通过执行以下操作来写入
id
name
,而无需写入
data

public class Something {
    private static final Logger logger = LoggerFactory.getLogger();
    private static final ObjectWriter loggingItemWriter = new ObjectMapper().writerWithView(Item.LoggingView.class);

    public void doSomething(Item item) {
        ...
        logger.info(loggingItemWriter.writeValueAsString(item));
        ...
    }
}

Jackson的JsonView注释应该允许您使用特定视图标记某些字段/getter。像下面这样的方法应该可以奏效

public class Item {
    public static class LoggingView {}

    @JsonView(LoggingView.class)
    public int id;

    @JsonView(LoggingView.class)
    public String name;

    public byte[] data;
}
这应该允许您通过执行以下操作来写入
id
name
,而无需写入
data

public class Something {
    private static final Logger logger = LoggerFactory.getLogger();
    private static final ObjectWriter loggingItemWriter = new ObjectMapper().writerWithView(Item.LoggingView.class);

    public void doSomething(Item item) {
        ...
        logger.info(loggingItemWriter.writeValueAsString(item));
        ...
    }
}
JSON指针 您可以使用由定义的JSON指针(用于标识JSON文档中特定值的字符串语法)

例如,考虑下面的JSON:

{
“名字”:“约翰”,
“姓氏”:“能源部”,
“地址”:{
“街道”:“第二街21号”,
“城市”:“纽约”,
“postalCode”:“10021-3100”,
“坐标”:{
“纬度”:40.7250387,
“经度”:-73.9932568
}
}
}
要查询
坐标
节点,可以使用以下JSON指针表达式:

<代码>/地址/坐标 JSON指针和Jackson Jackson 2.3.0引入了对JSON指针的支持,可以如下使用:

public class Something {
    private static final Logger logger = LoggerFactory.getLogger();
    private static final ObjectWriter loggingItemWriter = new ObjectMapper().writerWithView(Item.LoggingView.class);

    public void doSomething(Item item) {
        ...
        logger.info(loggingItemWriter.writeValueAsString(item));
        ...
    }
}
String json=“{\“firstName\”:“John\”,“lastName\”:“Doe\”,“address\”:{“street\”:“
+“第二街21号”“纽约市”“邮政编码”“10021-3100”“,”
+“\”坐标\“:{\”纬度\“:40.7250387,\”经度\“:-73.9932568}}”;
ObjectMapper mapper=新的ObjectMapper();
JsonNode=mapper.readTree(json);
JsonNode coordinatesNode=node.at(“/address/coordinates”);
坐标
节点可以解析为bean:

Coordinates坐标=mapper.treeToValue(Coordinates节点,Coordinates.class);
或者可以写为
字符串

String coordinates nodeasstring=mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(协调节点);
乱穿马路 JSON指针的一个很好的替代方法是JSONPath。在Java中,有一个名为的实现,它与Jackson集成

要使用JsonPath查询
坐标
节点,可以使用以下表达式:

$.address.coordinates
查询节点的代码如下所示:

JsonNode coordinatesNode=JsonPath.parse(json)
.read(“$.address.coordinates”,JsonNode.class);
JsonPath需要以下依赖项:


com.jayway.jsonpath

  • 阅读并理解如何正确使用它。

    JSON指针 您可以使用由定义的JSON指针(用于标识JSON文档中特定值的字符串语法)

    例如,考虑下面的JSON:

    {
    “名字”:“约翰”,
    “姓氏”:“能源部”,
    “地址”:{
    “街道”:“第二街21号”,
    “城市”:“纽约”,
    “postalCode”:“10021-3100”,
    “坐标”:{
    “纬度”:40.7250387,
    “经度”:-73.9932568
    }
    }
    }
    
    要查询
    坐标
    节点,可以使用以下JSON指针表达式:

    /地址/坐标
    
    JSON指针和Jackson Jackson 2.3.0引入了对JSON指针的支持,可以如下使用:

    public class Something {
        private static final Logger logger = LoggerFactory.getLogger();
        private static final ObjectWriter loggingItemWriter = new ObjectMapper().writerWithView(Item.LoggingView.class);
    
        public void doSomething(Item item) {
            ...
            logger.info(loggingItemWriter.writeValueAsString(item));
            ...
        }
    }
    
    String json=“{\“firstName\”:“John\”,“lastName\”:“Doe\”,“address\”:{“street\”:“
    +“第二街21号”“纽约市”“邮政编码”“10021-3100”“,”
    +“\”坐标\“:{\”纬度\“:40.7250387,\”经度\“:-73.9932568}}”;
    ObjectMapper mapper=新的ObjectMapper();
    JsonNode=mapper.readTree(json);
    JsonNode coordinatesNode=node.at(“/address/coordinates”);
    
    坐标
    节点可以解析为bean:

    Coordinates坐标=mapper.treeToValue(Coordinates节点,Coordinates.class);
    
    或者可以写为
    字符串

    String coordinates nodeasstring=mapper.writerWithDefaultPrettyPrinter()
    .writeValueAsString(协调节点);
    
    乱穿马路 JSON p的一个很好的替代方案