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

查找Json-path/(任何API)以更新Java中给定json字符串中的任何值

姜德泽
2023-03-14

Inshort:我试图找到一些api,通过将第一个参数作为jsonString,第二个参数作为JSONPath,第三个参数将是该参数的新值来改变值。但是,我发现的只是这个。。https://code.google.com/p/json-path/

这个api允许我在JSON字符串中查找任何值。但是,我没有找到简单的方法来更新任何键的值。例如,这里有一本书。json。

{
"store":{
    "book":[
        {
            "category":"reference",
            "author":"Nigel Rees",
            "title":"Sayings of the Century",
            "price":8.95
        },
        {
            "category":"fiction",
            "author":"Evelyn Waugh",
            "title":"Sword of Honour",
            "price":12.99,
            "isbn":"0-553-21311-3"
        }
    ],
    "bicycle":{
        "color":"red",
        "price":19.95
    }
   }
 }

我可以通过这样做访问自行车的颜色。

String bicycleColor = JsonPath.read(json, "$.store.bicycle.color");

但我正在JsonPath或其他api中寻找这样的方法

    JsonPath.changeNodeValue(json, "$.store.bicycle.color", "green");
    String bicycleColor = JsonPath.read(json, "$.store.bicycle.color");
    System.out.println(bicycleColor);  // This should print "green" now. 

我排除了这些选项,

  • 创建一个新的JSON字符串

原因:对于不同类型的服务,我有大约500个不同的请求,这些请求返回不同的json结构。所以,我不想总是手动创建新的JSON字符串。因为,ID在json结构中是动态的。

任何想法或方向都值得赞赏。

用以下答案更新此问题。

>

  • 复制MutableJson.java.
  • 复制这个小片段并根据需要进行修改。

    private static void updateJsonValue() {
    
    JSONParser parser = new JSONParser();
    JSONObject jsonObject = new JSONObject();
    
    FileReader reader = null;
    try {
        File jsonFile = new File("path to book.json");
        reader = new FileReader(jsonFile);
        jsonObject = (JSONObject) parser.parse(reader);
    
    } catch (Exception ex) {
        System.out.println(ex.getLocalizedMessage());
    }
    
    Map<String, Object> userData = null;
    try {
        userData = new ObjectMapper().readValue(jsonObject.toJSONString(), Map.class);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    
    MutableJson json = new MutableJson(userData);
    
    System.out.println("Before:\t" + json.map());
    
    json.update("$.store.book[0].author", "jigish");
    json.update("$.store.book[1].category", "action");
    
    System.out.println("After:\t" + json.map().toString());
    
    }
    

    使用这些库。

    • 导入org.json.simple.JSONObject;
    • 导入org.json.simple.parser.JSONParser;
    • 导入org.codehaus.jackson.map.ObjectMapper;
  • 共有3个答案

    卞俊哲
    2023-03-14

    只是回答人们登陆此页面的未来参考。

    您可以考虑使用jsonpatch的Java实现。RFC可以在这里找到

    JSON补丁是一种描述JSON文档更改的格式。它可以用来避免在只有一部分发生更改时发送整个文档。当与HTTP补丁方法结合使用时,它允许以符合标准的方式对HTTP API进行部分更新。

    您可以指定需要执行的操作(替换、添加......)、必须执行的json路径以及应该使用的值。

    同样,以RFC为例:

     [
         { "op": "test", "path": "/a/b/c", "value": "foo" },
         { "op": "remove", "path": "/a/b/c" },
         { "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
         { "op": "replace", "path": "/a/b/c", "value": 42 },
         { "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
         { "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }
       ]
    

    对于Java实现,我自己没有使用过,但您可以尝试https://github.com/fge/json-patch

    邹宣
    2023-03-14

    假设已解析的JSON可以在内存中表示为映射,则可以构建类似于JsonPath的API,如下所示:

    void update(Map<String, Object> json, String path, Object newValue);
    

    我已经快速完成了一个简单的特定路径(不支持条件和通配符)的脏实现的要点,这些路径可以遍历json树,例如$.store.name,$.store.books[0]. isbn。在这里:MutableJson.java.它肯定需要改进,但可以给一个好的开始。

    用法示例:

    import java.util.*;
    
    public class MutableJson {
    
        public static void main(String[] args) {
            MutableJson json = new MutableJson(
                    new HashMap<String, Object>() {{
                        put("store", new HashMap<String, Object>() {{
                            put("name", "Some Store");
                            put("books", Arrays.asList(
                                    new HashMap<String, Object>() {{
                                        put("isbn", "111");
                                    }},
                                    new HashMap<String, Object>() {{
                                        put("isbn", "222");
                                    }}
                            ));
                        }});
                    }}
            );
    
            System.out.println("Before:\t" + json.map());
    
            json.update("$.store.name", "Book Store");
            json.update("$.store.books[0].isbn", "444");
            json.update("$.store.books[1].isbn", "555");
    
            System.out.println("After:\t" + json.map());
        }
    
        private final Map<String, Object> json;
    
        public MutableJson(Map<String, Object> json) {
            this.json = json;
        }
    
        public Map<String, Object> map() {
            return json;
        }
    
        public void update(String path, Object newValue) {
            updateJson(this.json, Path.parse(path), newValue);
        }
    
        private void updateJson(Map<String, Object> data, Iterator<Token> path, Object newValue) {
            Token token = path.next();
            for (Map.Entry<String, Object> entry : data.entrySet()) {
                if (!token.accept(entry.getKey(), entry.getValue())) {
                    continue;
                }
    
                if (path.hasNext()) {
                    Object value = token.value(entry.getValue());
                    if (value instanceof Map) {
                        updateJson((Map<String, Object>) value, path, newValue);
                    }
                } else {
                    token.update(entry, newValue);
                }
            }
        }
    }
    
    class Path {
        public static Iterator<Token> parse(String path) {
            if (path.isEmpty()) {
                return Collections.<Token>emptyList().iterator();
            }
            if (path.startsWith("$.")) {
                path = path.substring(2);
            }
    
            List<Token> tokens = new ArrayList<>();
            for (String part : path.split("\\.")) {
                if (part.matches("\\w+\\[\\d+\\]")) {
                    String fieldName = part.substring(0, part.indexOf('['));
                    int index = Integer.parseInt(part.substring(part.indexOf('[')+1, part.indexOf(']')));
                    tokens.add(new ArrayToken(fieldName, index));
                } else {
                    tokens.add(new FieldToken(part));
                }
            };
    
            return tokens.iterator();
        }
    }
    
    abstract class Token {
    
        protected final String fieldName;
    
        Token(String fieldName) {
            this.fieldName = fieldName;
        }
    
        public abstract Object value(Object value);
    
        public abstract boolean accept(String key, Object value);
    
        public abstract void update(Map.Entry<String, Object> entry, Object newValue);
    }
    
    class FieldToken extends Token {
    
        FieldToken(String fieldName) {
            super(fieldName);
        }
    
        @Override
        public Object value(Object value) {
            return value;
        }
    
        @Override
        public boolean accept(String key, Object value) {
            return fieldName.equals(key);
        }
    
        @Override
        public void update(Map.Entry<String, Object> entry, Object newValue) {
            entry.setValue(newValue);
        }
    }
    
    class ArrayToken extends Token {
    
        private final int index;
    
        ArrayToken(String fieldName, int index) {
            super(fieldName);
            this.index = index;
        }
    
        @Override
        public Object value(Object value) {
            return ((List) value).get(index);
        }
    
        @Override
        public boolean accept(String key, Object value) {
            return fieldName.equals(key) && value instanceof List && ((List) value).size() > index;
        }
    
        @Override
        public void update(Map.Entry<String, Object> entry, Object newValue) {
            List list = (List) entry.getValue();
            list.set(index, newValue);
        }
    }
    

    JSON字符串可以使用Jackson轻松解析为映射:

    Map<String,Object> userData = new ObjectMapper().readValue("{ \"store\": ... }", Map.class);
    
    孙京
    2023-03-14

    问题是您想要的功能已经是JsonPath的一个未文档化的功能。使用json结构的示例:

    String json = "{ \"store\":{ \"book\":[ { \"category\":\"reference\", \"author\":\"Nigel Rees\", \"title\":\"Sayings of the Century\", \"price\":8.95 }, { \"category\":\"fiction\", \"author\":\"Evelyn Waugh\", \"title\":\"Sword of Honour\", \"price\":12.99, \"isbn\":\"0-553-21311-3\" } ], \"bicycle\":{ \"color\":\"red\", \"price\":19.95 } } }";
    DocumentContext doc = JsonPath.parse(json).
        set("$.store.bicycle.color", "green").
        set("$.store.book[0].price", 9.5);
    String newJson = new Gson().toJson(doc.read("$"));
    
     类似资料:
    • 问题内容: 我正在寻找一种在字符串中查找JSON数据的方法。像wordpress简码一样思考它。我认为最好的方法是使用正则表达式。我不想解析JSON,只需查找所有出现的事件。 正则表达式中是否有办法使括号的数量匹配?目前,当我嵌套对象时遇到了这个问题。 演示的快速示例: 结果,我想要两个JSON字符串。谢谢! 问题答案: 从给定的文本中提取JSON字符串 由于您正在寻找一种简单的解决方案,因此可以

    • 下面是我的JSON: 我想用下面的规则更新上述JSON字符串的两个属性: 标志:我想盲目地将此属性更新为。 infoFlag:如果< code>info的< code>name属性为< code>null,那么我希望将< code>infoFlag更新为< code>true否则为< code>false,如果它为< code>not null。 因此,在用这些规则更新JSON之后,我希望将JSO

    • 问题内容: 我想找到字符串中任何“特殊”字符首次出现的索引,如下所示: …除非那是无效的Python语法。当然,我可以编写一个模拟此行为的函数: 我也可以使用正则表达式,但两种解决方案似乎都有些过分。在Python中有什么“明智”的方法吗? 问题答案: 您可以将enumerate和next与生成器表达式一起使用,获取第一个匹配项,或者如果s中没有字符,则返回None: 如果没有匹配项,则可以将您想

    • 问题内容: 如何在Java中验证JSON字符串?还是可以使用正则表达式解析它? 问题答案: 一个疯狂的主意,尝试解析它并捕获异常: 该代码使用org.json JSON API实现,该实现在github,maven和部分Android上可用。

    • 我有一个json,它有一个标签“msg”。现在,如果搜索结果以json格式显示,那么这个标签就不存在了。当搜索结果为0时,这个标签的值为not found。 现在我想检查这个标签是否存在。那么如何做到这一点 以下是未找到记录时的json示例:

    • 需要验证的字符串采用以下格式,严格来说它不是JSON,不能使用PHP的JSON编码过程进行验证。请注意,键中的%%是必需的。 当前正则表达式成功验证了上述内容: 有效示例:https://regex101.com/r/4y1uEu/1 无效示例(第二个值周围没有引号):https://regex101.com/r/4y1uEu/2 值需要支持其他字符,最好是任何字符,所以我将REGEX更改为 与此