Carell
Carell

Reputation: 95

Convert two arrays into one JSON object using Newtonsoft.Json

I have the arrays name[] and lastname[]. How do I combine and convert them into a JSON string? I want it to be in the following format. I need the "Employees" title in the JSON.

{ "Employees" : [
    {"name": "John", "lastname": "Coleman"},
    {"name": "Chip", "lastname": "Dale"},
    {"name": "Ann", "lastname": "Smith"},
    {"name": "Terry", "lastname": "Johnson"},
    {"name": "Mary", "lastname": "Loggins"},
    {"name": "Timothy", "lastname": "Lopez"},
    {"name": "Jessica", "lastname": "Brown"}
]}

I need an efficient way to do this as the arrays have a lot of items in them. I actually have more than two arrays that I need to combine into a JSON object. For simplicity I demonstrated what I want with two. They all have the same number of items and are ordered. I do not want to iterate the arrays and construct the JSON string myself.

Update:

I forgot to mention that my arrays are IEnumerable<[]> both string and integer arrays. Here is what I tried the arrays are created in another class.

  public string[] Name {
                get{ return  (Employees ?? Enumerable.Empty<Employee> ()).Select (p => p.name).ToArray(); }
            }

    public string[] Lastname {
                get{ return  (Employees ?? Enumerable.Empty<Employee> ()).Select (p => p.lastname).ToArray(); }
            }

    public int[] Age {
                get{ return  (Employees ?? Enumerable.Empty<Employee> ()).Select (p => p.age).ToArray(); }
            }

I then access them

var name = X.Select(s => s.Name).ToArray();
var lastname = X.Select(s => s.Lastname).ToArray();
var age = X.Select(s => s.Age).ToArray();

var employees = new { Employees = Enumerable.Range(0, name.Length).Select(i => new { name = name[i], lastname = lastname[i], age = age[i] }) };
var json = JsonConvert.SerializeObject(employees, Formatting.Indented);
Debug.WriteLine(json);

For some reason this returns something similar to

{"Employees":[{"name":["John","Chip","Ann","Terry"],"lastname":["Coleman","Dale","Smith","Johnson"],"age":[42, 26, 33, 24]}]}

where all the names, lastnames are all put together. How do I get the correct format?

Upvotes: 7

Views: 2835

Answers (1)

dbc
dbc

Reputation: 117036

You can combine them with Zip() into an anonymous type, then serialize that:

        string[] name = new string[] { "John", "Chip" };
        string[] lastname = new string[] { "Coleman", "Dale" };

        var employees = new { Employees = name.Zip(lastname, (n1, n2) => new { name = n1, lastname = n2 }) };
        var json = JsonConvert.SerializeObject(employees, Formatting.Indented);
        Debug.WriteLine(json);

Which outputs:

{
  "Employees": [
    {
      "name": "John",
      "lastname": "Coleman"
    },
    {
      "name": "Chip",
      "lastname": "Dale"
    }
  ]
}

For multiple arrays, it might be easier to use Enumerable.Range() to iterate through the arrays in parallel:

        string[] name = new string[] { "John", "Chip" };
        string[] lastname = new string[] { "Coleman", "Dale" };
        string[] title = new string[] { "Mr", "Dr" };
        string[] profession = new string[] { "Coder", "Doctor" };

        var employees2 = new { Employees = Enumerable.Range(0, name.Length).Select(i => new { title = title[i], name = name[i], lastname = lastname[i], profession = profession[i] }) };
        var json2 = JsonConvert.SerializeObject(employees2, Formatting.Indented);
        Debug.WriteLine(json2);

Update

If your strings are in an IEnumerable<String[]>, you can convert that outer enumerable to an array then index into it. For instance, given the following test case:

        string[] name = new string[] { "John", "Chip" };
        string[] lastname = new string[] { "Coleman", "Dale" };
        string[] title = new string[] { "Mr", "Dr" };
        string[] profession = new string[] { "Coder", "Doctor" };

        IEnumerable<string[]> strings = new[] { title, name, lastname, profession };

You could do:

        var stringArray = strings.ToArray();

        var employees2 = new { Employees = Enumerable.Range(0, name.Length).Select(i => new { title = stringArray[0][i], name = stringArray[1][i], lastname = stringArray[2][i], profession = stringArray[3][i] }) };
        var json2 = JsonConvert.SerializeObject(employees2, Formatting.Indented);
        Debug.WriteLine(json2);

Which results in:

{
  "Employees": [
    {
      "title": "Mr",
      "name": "John",
      "lastname": "Coleman",
      "profession": "Coder"
    },
    {
      "title": "Dr",
      "name": "Chip",
      "lastname": "Dale",
      "profession": "Doctor"
    }
  ]
}

Update 2

If you actually have an enumeration of objects containing enumeration of employees, you can flatten them with Enumerable.SelectMany. For instance, given the following classes:

public class Employee
{
    public string name { get; set; }
    public string lastname { get; set; }
    public int age { get; set; }
    public string someMoreDataThatShouldNotBeSerialized { get; set; }
}

public class EmployeeContainer
{
    public IEnumerable<Employee> Employees { get; set; }
}

You could flatten them as follows:

        var X = GetAllEmployees();

        var employees = X.SelectMany(s => s.Employees ?? Enumerable.Empty<Employee>()).Select(e => new { name = e.name, lastname = e.lastname, age = e.age });
        var json = JsonConvert.SerializeObject(employees, Formatting.Indented);
        Debug.WriteLine(json);

Then the test setup

    public static IEnumerable<EmployeeContainer> GetAllEmployees()
    {
        return new[] { 
            new EmployeeContainer { 
                Employees = 
                    new[] { 
                        new Employee { name = "John", lastname = "Coleman", age = 42, someMoreDataThatShouldNotBeSerialized = "someMoreData1" },
                        new Employee { name = "Chip", lastname = "Dale", age = 26, someMoreDataThatShouldNotBeSerialized = "someMoreData2" },
                    } 
            },
            new EmployeeContainer { 
                Employees = 
                    new[] { 
                        new Employee { name = "Ann", lastname = "Smith", age = 33, someMoreDataThatShouldNotBeSerialized = "someMoreData3" },
                        new Employee { name = "Terry", lastname = "Johnson", age = 24, someMoreDataThatShouldNotBeSerialized = "someMoreData4" }, 
                    } 
            },
            new EmployeeContainer()
        };
    }

Produces:

[
  {
    "name": "John",
    "lastname": "Coleman",
    "age": 42
  },
  {
    "name": "Chip",
    "lastname": "Dale",
    "age": 26
  },
  {
    "name": "Ann",
    "lastname": "Smith",
    "age": 33
  },
  {
    "name": "Terry",
    "lastname": "Johnson",
    "age": 24
  }
]

Working fiddle.

Upvotes: 7

Related Questions