Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set JSON attribute by path

Tags:

json

c#

json.net

Is there a way to set an attribute by the path, using Json.NET?

JObject o = JObject.Parse(@"{
'CPU': 'Intel',
'Drivers': {
   'Mouse': 'HPQ',
   'VideoCard' : 'NVidia'
   }
}");

//something like that
o.SetByPath("Drivers.VideoCard") = "Intel";

Is it possible?

By the way, I know that I can do this:

o["Drivers"]["VideoCard"] = "Intel";

but that's not what I'm looking for.

like image 640
Arquitecto Avatar asked Nov 20 '15 14:11

Arquitecto


2 Answers

The JObject.SelectToken and JToken.Replace methods can be used here to achieve essentially the same effect.

static void Main(string[] args)
{
    JObject obj = JObject.Parse(@"{
      'CPU': 'Intel',
      'Drivers': {
        'Mouse': 'HPQ',
        'VideoCard' : 'NVidia'
       }
    }");
    Console.WriteLine(obj);

    JToken token = obj.SelectToken("Drivers.VideoCard");
    token.Replace("Intel");
    Console.WriteLine(obj);
}

Output:

{
  "CPU": "Intel",
  "Drivers": {
    "Mouse": "HPQ",
    "VideoCard": "NVidia"
  }
}
{
  "CPU": "Intel",
  "Drivers": {
    "Mouse": "HPQ",
    "VideoCard": "Intel"
  }
}

Toss it in an extension method if you'd like.

static void SetByPath(this JObject obj, string path, string value)
{
    JToken token = obj.SelectToken(path);
    token.Replace(value);
}
like image 59
senshin Avatar answered Nov 12 '22 13:11

senshin


The following method will get an inner object / value from a path similar to the one you provided on the question:

public static object GetObjectFromPath(dynamic obj, string path)
{
     string[] segments = path.Split('.');
     foreach(string segment in segments)
        obj = obj[segment];
     return obj;
}

You would call it like this:

// Providing that 'o' is the JObject in your question

object result = GetObjectFromPath(o, "Drivers");
// result will be of type JObject because it is an inner json object
JObject innerObject = (JObject)result;

object value = GetObjectFromPath(o, "Drivers.VideoCard");
// You may also do GetObjectFromPath(innerObject, "VideoCard");
// value will be of type JValue because it is a json value
JValue innerValue = (JValue)result;

// You may get the .NET primite value calling the 'Value' property:
object stringValue = (string)innerValue.Value;

//You may also set the value
innerValue.Value = "Intel";
like image 36
Matias Cicero Avatar answered Nov 12 '22 12:11

Matias Cicero