11
string json = "{\"People\":[{\"FirstName\":\"Hans\",\"LastName\":\"Olo\"}
                            {\"FirstName\":\"Jimmy\",\"LastName\":\"Crackedcorn\"}]}";

var obj = JObject.Parse(json);

List<string> first;
List<string> last;

foreach (var child in obj["People"].Children())
{
    var name = child.First()["countryName"].ToString();
    var two = child.First()["countryCode"].ToString();
    var three = child.First()["isoAlpha3"].ToString();

    countries.Add(name);
    twoCharCodes.Add(two);
    threeCharCodes.Add(three);

    Console.Write("Name:\t\t{0}\n2CharCode:\t{1}\n3CharCode:\t{2}\n\n", name, two, three);
}

I'm looking for a way to add each FirstName value into the first List and the same with the LastName vaues and the last List. What is the best way to go about doing this?

The above code breaks on:

var name = child.First()["countryName"].ToString();

with this error:

 Cannot access child value on Newtonsoft.Json.Linq.JProperty

Any advice?

3
  • 6
    am I missing something? Where are you coming up with countryName and the others? All I see are FirstName and LastName under People Commented Aug 28, 2015 at 14:44
  • , missing between objects. Commented Aug 28, 2015 at 14:46
  • Hans Olo - someone been watching Stargate? Commented Jun 14, 2021 at 1:29

5 Answers 5

19

Seems like a bad way to do it (creating two correlated lists) but I'm assuming you have your reasons.

I'd parse the JSON string (which has a typo in your example, it's missing a comma between the two objects) into a strongly-typed object and then use a couple of LINQ queries to get the two lists.

void Main()
{
    string json = "{\"People\":[{\"FirstName\":\"Hans\",\"LastName\":\"Olo\"},{\"FirstName\":\"Jimmy\",\"LastName\":\"Crackedcorn\"}]}";

    var result = JsonConvert.DeserializeObject<RootObject>(json);

    var firstNames = result.People.Select (p => p.FirstName).ToList();
    var lastNames = result.People.Select (p => p.LastName).ToList();
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class RootObject
{
    public List<Person> People { get; set; }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Awesome, this worked great! Thanks a bunch. I'm making two lists to eventually write the values to a database. I figured this way I can easily accomplish this with a simple for loop. Do you have any alternatives?
10

Since you are using JSON.NET, personally I would go with serialization so that you can have Intellisense support for your object. You'll need a class that represents your JSON structure. You can build this by hand, or you can use something like json2csharp to generate it for you:

e.g.

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class RootObject
{
    public List<Person> People { get; set; }
}

Then, you can simply call JsonConvert's methods to deserialize the JSON into an object:

RootObject instance = JsonConvert.Deserialize<RootObject>(json);

Then you have Intellisense:

var firstName = instance.People[0].FirstName;
var lastName = instance.People[0].LastName;

4 Comments

You mean basically the same answer I posted two minutes before yours? :-)
Sure. I was still typing as you were posting. I did give credit to the website that you also used to generate your classes ; )
@KennethK.: Getting Null with this code RootObject instance = JsonConvert.DeserializeObject<RootObject>(json); My json string is {\r\n \"People\":[\r\n {\r\n "{\r\n \"People\": [\r\n {\r\n \"FirstName\": \"Hans\",\r\n \"LastName\": \"Olo\"\r\n },\r\n {\r\n \"FirstName\": \"Jimmy\",\r\n \"LastName\": \"Crackedcorn\"\r\n },\r\n {\r\n \"FirstName\": \"Tim\",\r\n \"LastName\": \"John\"\r\n }\r\n ]\r\n} \r\n\r\n"
@venkat Your JSON doesn't match the structure that this question's code represents. And this should probably be a new question.
1

I use this JSON Helper class in my projects. I found it on the net a year ago but lost the source URL. So I am pasting it directly from my project:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization.Json;
using System.IO;
using System.Text;
/// <summary>
/// JSON Serialization and Deserialization Assistant Class
/// </summary>
public class JsonHelper
{
    /// <summary>
    /// JSON Serialization
    /// </summary>
    public static string JsonSerializer<T> (T t)
    {
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
        MemoryStream ms = new MemoryStream();
        ser.WriteObject(ms, t);
        string jsonString = Encoding.UTF8.GetString(ms.ToArray());
        ms.Close();
        return jsonString;
    }
    /// <summary>
    /// JSON Deserialization
    /// </summary>
    public static T JsonDeserialize<T> (string jsonString)
    {
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
        MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
        T obj = (T)ser.ReadObject(ms);
        return obj;
    }
}

You can use it like this: Create the classes as Craig W. suggested.

And then deserialize like this

RootObject root = JSONHelper.JsonDeserialize<RootObject>(json);

4 Comments

My understanding is that the DataContractJsonSerializer is much slower than JSON.NET's serializer, which--if memory serves--is why the ASP.NET team switched to JSON.NET for the default JSON serializer. Speed may not be an issue here, but may be of future consideration.
@KennethK. yeah it depends on project scenario. Like in my case I never had performance issues with this code. It's just another option for OP. Rest depends on his project demands.
Excellent solution! But it should have been mentioned for new users that the class to be serialized must be annotated with attribute [DataContract] and all its properties to be serialized with attribute [DataMember], and may be the ones that you don't want to serialize with [IgnoreDataMember] attribute.
@Kenneth K. NewtonSoft's dll takes around 700 kb. In my case, system's memory WAS of concern. Plus Newtonsoft.json (or JSon.Net) was throwing exception at target system while this code embedded inside my project being a regular class. But your comment is very important to make users conscious about performance vs memory compromise.
1

Wanted to post this as a comment as a side note to the accepted answer, but that got a bit unclear. So purely as a side note:

If you have no need for the objects themselves and you want to have your project clear of further unused classes, you can parse with something like:

var list = JObject.Parse(json)["People"].Select(el => new { FirstName = (string)el["FirstName"], LastName = (string)el["LastName"] }).ToList();

var firstNames = list.Select(p => p.FirstName).ToList();
var lastNames = list.Select(p => p.LastName).ToList();

Even when using a strongly typed person class, you can still skip the root object by creating a list with JObject.Parse(json)["People"].ToObject<List<Person>>() Of course, if you do need to reuse the objects, it's better to create them from the start. Just wanted to point out the alternative ;)

Comments

0

Try this:

using System;
using Newtonsoft.Json;
using System.Collections.Generic;
public class Program
{
    public static void Main()
    {
        List<Man> Men = new List<Man>();

        Man m1 = new Man();
        m1.Number = "+1-9169168158";
        m1.Message = "Hello Bob from 1";
        m1.UniqueCode = "0123";
        m1.State = 0;

        Man m2 = new Man();
        m2.Number = "+1-9296146182";
        m2.Message = "Hello Bob from 2";
        m2.UniqueCode = "0125";
        m2.State = 0;

        Men.AddRange(new Man[] { m1, m2 });

        string result = JsonConvert.SerializeObject(Men);
        Console.WriteLine(result);  

        List<Man> NewMen = JsonConvert.DeserializeObject<List<Man>>(result);
        foreach(Man m in NewMen) Console.WriteLine(m.Message);
    }
}
public class Man
{
    public string Number{get;set;}
    public string Message {get;set;}
    public string UniqueCode {get;set;}
    public int State {get;set;}
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.