Editing JSON using JSONPath

2019-02-10 18:11发布

Hello SO community :)!

I want to create method which will let user to edit (or add) JSON specific value or object (located in JSON by JSONPath). Below simple example what is on my mind. User always enters JSON, JSONPath and value/object to change. I'm using Json.NET library.

Method input {json, jsonpath, valuetoedit} || output {new json as string}

Example input:

{ "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
      },
      { "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

Example JSONPath:

$.store.book[*].author

Example value to change:

NewAuthorSpecifiedByUser

Output - new JSON where all authors will be changed to 'NewAuthorSpecifiedByUser'.

Is that even possible?

标签: c# json jsonpath
1条回答
可以哭但决不认输i
2楼-- · 2019-02-10 18:32

The 3rd party package allows this to be done easily:

  1. Parse the JSON into a LINQ to JSON hierarchy of JToken tokens.

  2. Select JSON values to modify via SelectTokens using a query string in JSONPath syntax.

  3. Using JToken.Replace() replace the selected values with the new values. A new value can be serialized directly to a JToken using JToken.FromObject().

Thus:

public static class JsonExtensions
{
    public static JToken ReplacePath<T>(this JToken root, string path, T newValue)
    {
        if (root == null || path == null)
            throw new ArgumentNullException();

        foreach (var value in root.SelectTokens(path).ToList())
        {
            if (value == root)
                root = JToken.FromObject(newValue);
            else
                value.Replace(JToken.FromObject(newValue));
        }

        return root;
    }    

    public static string ReplacePath<T>(string jsonString, string path, T newValue)
    {
        return JToken.Parse(jsonString).ReplacePath(path, newValue).ToString();
    }    
}

Then use it like:

var newJsonAuthorString = JsonExtensions.ReplacePath(jsonString, @"$.store.book[*].author", "NewAuthorSpecifiedByUser");

Prototype fiddle. If you are going to allow the user to do a series of edits, it will likely be more efficient to keep your JSON in a JToken hierarchy permanently rather that repeatedly converting from and to a string representation.

See also How to install JSON.NET using NuGet?.

查看更多
登录 后发表回答