skip to Main Content

Below is the json in a very simplified form (the original contains many more items). I want to add the "acf" content of all items to List

[{
    "id": 26,
    "date": "2023-08-30T18:36:24",
    "date_gmt": "2023-08-30T18:36:24",  
    "acf": {
        "name": "John",
        "lastName": "Smith",
        "age": "33"     
    }
}, {
    "id": 20,
    "date": "2023-06-11T11:17:02",
    "date_gmt": "2023-06-11T11:17:02",
    "acf": {
        "name": "Randy",
        "lastName": "Jones ",
        "age": "22"     
    }
},
{
    "id": 20,
    "date": "2023-06-11T11:17:02",
    "date_gmt": "2023-06-11T11:17:02",
    "acf": {
        "name": "Mark",
        "lastName": "Taylor ",
        "age": "56" 
    }       
}]
    public class Acf
    {
        public string name { get; set; }
        public string lastName { get; set; }
        public string age { get; set; }
    }

Below is an example of how I tried to solve it. Surely there is a better and simpler way to solve this task. Thank you for your help.

  [System.Serializable]
  public class Acf
  {
        public string name { get; set; }
        public string lastName { get; set; }
        public string age { get; set; }
  }
 
  private List<Acf> _acfList = new List<Acf>();
 
 
 void PrepareAcfData(string json)
 {
 
 JArray data = JArray.Parse(json);
 
  for (int i = 0; i < data.Count; i++)
  {
    Acf newAcf = new Acf();
       
    newAcf.name = data[i]["acf"]["name"].Value<string>();
    newAcf.lastName = data[i]["acf"]["lastName"].Value<string>();
    newAcf.lastName = data[i]["acf"]["age"].Value<int>();
        
        _acfList.Add(newAcf);
  }
 }

2

Answers


  1. You could combine JToken.SelectTokens() using a JSONPath wildcard expression with JToken.ToObject<T>() to simplify your code:

    var _acfList = root.SelectTokens("[*].acf").Select(t => t.ToObject<Acf>()).ToList();
    

    You could also use anonymous types to deserialize only selected parts of your JSON:

    var _acfList = JsonConvert.DeserializeAnonymousType(json, new [] { new { acf = default(Acf) }})
        .Select(a => a.acf)
        .ToList();
    

    Notes:

    • [*] is the JSONPath wildcard operator selecting all items in an array.

    • [*].acf] selects the value of the property "acf" in each array object.

    • ToObject<Acf>() converts each of those to your final model.

    • If your JSON were more complex, say with some outer container object {"root":[/* The array above*/ ]}, you could add that in as follows:

      root.SelectTokens("root[*].acf").Select(t => t.ToObject<Acf>()).ToList();
      
    • Deserializing directly to anonymous types may be more performant that parsing to an intermediate JToken hierarchy.

    Demo fiddle for SelectTokens here and for anonymous types here.

    Login or Signup to reply.
  2. Just use Linq

        List<Acf> _acfList = JArray.Parse(json)
                                   .Select(ja => ja["acf"].ToObject<Acf>())
                                   .ToList();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search