Stefan
Stefan

Reputation: 337

Restructuring a JSON object in C#

I have some JSON data that looks like this:

[
  {
    "name": "foo",
    "id": 1,
    "child": {
          name: "A",
          id: 1,
     }
  },
  {
    "name": "bar",
    "id": 1,
    "child": {
          name: "A",
          id: 1,
     }
  },
  {
    "name": "baz",
    "id": 2,
    "child": {
          name: "B",
          id: 2,
     }
  },
  {
    "name": "alpha",
    "id": 1,
    "child": {
          name: "A",
          id: 1,
     }
  }
]

I'm loading it into my .NET project and trying to restructure it so that it returns a response that looks something like this:

[
  {
    "name": "A"
    "id": 1,
    "parents": [
        {
          "name": "foo",
          "id": 1,
        },
        {
           "name": "bar",
           "id": 1,
        },
        {
           "name": "alpha",
           "id": 1,
        }
     ]
  },
  {
    "name": "B"
    "id": 2,
    "parents": [
        {
          "name": "baz",
          "id": 2,
        }
     ]
  }
]

I was able to use LINQ to grab all the IDs that matched, but only for 1 ID.

var test = deserializedJsonData.Where(w => w.child.id == SomeID).Select(s => s).ToList()

The moment I tried to iterate "SomeID" inside of a loop to iterate it, it freezes and crashes.

Is there a more efficient way of doing this?

EDIT: Corrected typo as pointed out in comments

Upvotes: 0

Views: 446

Answers (1)

Zunayed Shahriar
Zunayed Shahriar

Reputation: 2723

Regarding your requirement, I've created the objects.

public class Base
{
    public int id { get; set; }
    public string name { get; set; }
}

public class Data : Base
{
    public Base child { get; set; }
}

public class RequiredData : Base
{
    public List<Base> parents { get; set; }
}

Then created a comparer to distinct your child objects.

public class BaseComparer : IEqualityComparer<Base>
{
    public bool Equals(Base x, Base y)
    {
        if (x.id.Equals(y.id) && (x.name.Equals(y.name)))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public int GetHashCode(Base obj)
    {
        unchecked
        {
            int hash = 100;
            hash = hash * 10 + obj.id.GetHashCode();
            hash = hash * 10 + obj.name.GetHashCode();
            return hash;
        }
    }
}

Finally,

string rawData = File.ReadAllText(@"your_json_file_path");
var parsedData = JsonConvert.DeserializeObject<Data[]>(rawData);
var childs = parsedData.GroupBy(g => g.child.id).Select(s => new Base()
{
    id = s.Key,
    name = s.Where(w => w.child.id == s.Key).First().child.name
}).ToList();
var result = parsedData.GroupBy(s => s.child).Select(s => 
new RequiredData()
{
    id = s.Key.id,
    name = s.Key.name,
    parents = parsedData.Where(w => w.child.id == s.Key.id).Select(x =>
    new Base()
    {
        id = x.id,
        name = x.name
    }).ToList()
}).Distinct(new BaseComparer()).ToList();
var jsonResult = JsonConvert.SerializeObject(result);

jsonResult will contain your required output.

Note: I'm using Newtonsoft.Json library for JSON operations.

Upvotes: 1

Related Questions