skip to Main Content

I am calling vendor Api to get json data, I want to convert that json to my custom structure.

Here is example

When I call student data, vendor returns data as below

{
 "Students": [
   {
     "FirstName":"Abc",
     "LastName":"pqr"
   },
   {
     "FirstName":"pqr",
     "LastName":"pqccr"
   }
]
}

When I call employee data, it returns as below

{
 "Employee": [
   {
     "FName":"Abc",
     "LName":"pqr"
   },
   {
     "FName":"pqr",
     "LName":"pqccr"
   }
]
}

I want to convert this to my own json format so that it would be easy to retrieve and manipulation something as below


{
 "Person": [

   {
     "First_Name":"Abc",
     "Last_Name":"pqr"
   },
   {
     "First_Name":"pqr",
     "Last_Name":"pqccr"
   }
]
}

I am using system.text.json to serialized and deserialize.

How can I convert to this common structure?

Trying with system.text.json to deserialize but don’t have any idea on how can I convert to common structure

3

Answers


  1. convert json objects to model and use addrange to assign the data. Tried an example as below.
    Consider test1 class as students and test2 as employee

    public class test1
    {
        public List<data> json1 { get; set; }
    }
    
    public class test2
    {
        public List<data> json2 { get; set; }
    }
    
    public class test3
    {
        public List<data> person { get; set; }
    }
    
    public class data
    {
        public string Name { get; set; }
        public int id { get; set; }
    }
        
        var jsonData1 = new test1();
        var jsonData2 = new test2();
        var jsonData3 = new test3();
    
        jsonData1.json1 = new List<data>();
        jsonData1.json1.Add(new data { id = 1, Name = "Abc" });
        jsonData2.json2 = new List<data>();
        jsonData3.person = new List<data>();
        jsonData2.json2.Add(new data { id = 2, Name = "xyz" });
        jsonData3.person.AddRange(jsonData1.json1);
        jsonData3.person.AddRange(jsonData2.json2);
        string jsonString1 = JsonSerializer.Serialize<test3>(jsonData3);
    
    Login or Signup to reply.
  2. I would recommend to deserialize data to dedicated types (StudentsResponse and EmployeeResponse for example) and map them to desired one (PersonHolder for example) and then work with that type (serialize, manipulate, etc).

    If for some reason you don’t want to do that you can look into the JsonNode APIs to dynamically manipulate JSON. For example handling can look something like the following (possibly should be split into 2 branches):

    Data:

    var json = """
            {
             "Employee": [
               {
                 "FName":"Abc",
                 "LName":"pqr"
               },
               {
                 "FName":"pqr",
                 "LName":"pqccr"
               }
            ]
            }
            """;
    
    var studentsRoot = JsonNode.Parse(json).AsObject();
    if (studentsRoot.Remove("Students", out var person) 
        || studentsRoot.Remove("Employee", out person))
    {
        var replacements = new[]
        {
            ("FirstName", "First_Name"),
            ("LastName", "Last_Name"),        
            ("FName", "First_Name"),
            ("LName", "Last_Name"),
        };
        foreach (var jsonNode in person.AsArray())
        {
            var obj = jsonNode.AsObject();
            foreach (var replacement in replacements)
            {
                if (obj.Remove(replacement.Item1, out var val))
                {
                    obj.Add(replacement.Item2, val);
                }
            }
        }
    
        studentsRoot.Add("Person", person);
    }
    
    var jsonString = studentsRoot.ToJsonString();
    
    Login or Signup to reply.
  3. There are multiple approaches to solve this task. The best option depends on the context:

    • Are you doing just on-the-fly JSON transformation? Or maybe you need to read different sources and deserialize them into objects to work with them in your application?
    • How many different data sources you have?
    • What is the probability of changes to the format you receive data in?

    In the generic case, I would define some interface like:

    interface IPeopleReader
    {
        IEnumerable<Person> Read(string json);
    }
    

    And implement it for each of the data sources (e.g. StudentReader and EmployeeReader).

    While you have the same structure with just different property names, you can have shared implementation like:

    class PeopleReader : IPeopleReader
    {
        private readonly string _collectionName;
        private readonly string _firstNameField;
        private readonly string _lastNameField;
     
        public PeopleReader(string collectionName, string firstNameField, string lastNameField)
        {
            _collectionName = collectionName;
            _firstNameField = firstNameField;
            _lastNameField = lastNameField;
        }
        
        public IEnumerable<Person> Read(string json)
        {
            var node = JsonNode.Parse(json);
            if (node?[_collectionName]?.AsArray() is { } array)
            {
                foreach (var item in array)
                {
                    if (item?.AsObject() is { } obj)
                    {
                        yield return new Person
                        {
                            FirstName = obj[_firstNameField]?.ToString(),
                            LastName = obj[_lastNameField]?.ToString()
                        };
                    }
                }
            }
        }
    }
    

    And just reuse it for your cases:

    class StudentReader() : PeopleReader("Students", "FirstName", "LastName") { }
    
    class EmployeeReader() : PeopleReader("Employee", "FName", "LName") { }
    

    This way you can be flexible about implementations: you don’t duplicate much code while the structure is the same and in case one of the sources will change its format, you can just update corresponding class to whatever code you want (e.g. define custom models within that class or do any other logic).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search