问题
Given the following code:
var context = JObject.FromObject(new
{
data = new
{
mom = "",
dad = "",
sibling = "",
cousin = ""
}
});
var path = "$.data.calculated";
var token = context.SelectToken(path);
token
will be null. Thus, of course, trying this will produce an exception:
token.Replace("500");
I've seen other examples about how to add properties to a JObject
, of course, but they all seem like you have to know something about the object structure beforehand. What I need to do is something like this:
if (token == null)
{
context.Add(path);
token = context.SelectToken(r.ContextTarget);
}
I could then use the replace method on the new token to set its' value. But context.Add(path) throws an exception:
"Can not add Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject."
How can I dynamically add a property using a full path like this, without knowing the existing object structure?
回答1:
While this isn't a catch-all (won't correctly do arrays for example), it does handle the above simple case and should provide for multiple levels into the hierarchy.
if (token == null)
{
var obj = CreateObjectForPath(path, newValue);
context.Merge(obj);
}
And the meat of the roll-your-own part:
private JObject CreateObjectForPath(string target, object newValue)
{
var json = new StringBuilder();
json.Append(@"{");
var paths = target.Split('.');
var i = -1;
var objCount = 0;
foreach (string path in paths)
{
i++;
if (paths[i] == "$") continue;
json.Append('"');
json.Append(path);
json.Append('"');
json.Append(": ");
if (i + 1 != paths.Length)
{
json.Append("{");
objCount++;
}
}
json.Append(newValue);
for (int level = 1; level <= objCount; level++)
{
json.Append(@"}");
}
json.Append(@"}");
var jsonString = json.ToString();
var obj = JObject.Parse(jsonString);
return obj;
}
来源:https://stackoverflow.com/questions/51310888/how-to-add-jobject-property-by-path-if-not-exists