skip to Main Content

I’m trying to convert a json input format into another json format by using c#.

The input format which is seen just below is gotten from a httpclient post request:

{
  "data": {
    "trafficData": {
      "volume": {
        "byHour": {
          "edges": [
            {
              "node": {
                "from": "2019-10-24T12:00:00+02:00",
                "to": "2019-10-24T13:00:00+02:00",
                "byDirection": [
                  {
                    "heading": "North",
                    "total": {
                      "volumeNumbers": {
                        "volume": 696
                      }
                    }
                  },
                  {
                    "heading": "South",
                    "total": {
                      "volumeNumbers": {
                        "volume": 726
                      }
                    }
                  }
                ]
              }
            },
            {
              "node": {
                "from": "2019-10-24T13:00:00+02:00",
                "to": "2019-10-24T14:00:00+02:00",
                "byDirection": [
                  {
                    "heading": "North",
                    "total": {
                      "volumeNumbers": {
                        "volume": 805
                      }
                    }
                  },
                  {
                    "heading": "South",
                    "total": {
                      "volumeNumbers": {
                        "volume": 751
                      }
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    }
  }
}

I wish to transform the json input to something similar to the output code just below:

{
   "data":[
      {
         "from":"2019-10-24T12:00:00+02:00",
         "to":"2019-10-24T13:00:00+02:00",
         "heading":"South",
         "volume":726
      },
      {
         "from":"2019-10-24T13:00:00+02:00",
         "to":"2019-10-24T14:00:00+02:00",
         "heading":"South",
         "volume":751
      }
   ]
}

In c# i have tried the below code: (also in connection with creating new class objects with https://json2csharp.com/)

//o1 is the json object input

IEnumerable<JToken> jTokens = o1.Descendants().Where(p => !p.HasValues);
            Dictionary<string, string> results = jTokens.Aggregate(new Dictionary<string, string>(), (properties, jToken) =>
            {
                properties.Add(jToken.Path, jToken.ToString());
                return properties;
            });

2

Answers


  1. try this code

    json = new JArray(JObject.Parse(json).SelectToken("data.trafficData.volume.byHour.edges")
                            .Select(o => new JObject
                            {
                                ["from"] = (string)o["node"]["from"],
                                ["to"] = (string)o["node"]["to"],
                                ["byDirection"] = new JArray(o["node"]["byDirection"]
                             .Select(o => new JObject
                             {
                                 ["heading"] = o["heading"],
                                 ["volume"] = o["total"]["volumeNumbers"]["volume"]
                             }))
                            })).ToString();
    
    Login or Signup to reply.
  2. I would personally use AutoMapper in this case.

    My answer will be written using .NET 6 Web API model (with AutoMapper package obviously installed first).

    I generated the C# classes with the tool you provided for my example.

    Let’s assume I have a Request.cs file as :

    using System.Text.Json.Serialization;
    namespace Something.Requests
    {
        // Root myDeserializedClass = JsonSerializer.Deserialize<Root>(myJsonResponse);
        public class ByDirection
        {
            [JsonPropertyName("heading")]
            public string heading { get; set; }
    
            [JsonPropertyName("total")]
            public Total total { get; set; }
        }
    
        public class ByHour
        {
            [JsonPropertyName("edges")]
            public List<Edge> edges { get; set; }
        }
    
        public class Data
        {
            [JsonPropertyName("trafficData")]
            public TrafficData trafficData { get; set; }
        }
    
        public class Edge
        {
            [JsonPropertyName("node")]
            public Node node { get; set; }
        }
    
        public class Node
        {
            [JsonPropertyName("from")]
            public DateTime from { get; set; }
    
            [JsonPropertyName("to")]
            public DateTime to { get; set; }
    
            [JsonPropertyName("byDirection")]
            public List<ByDirection> byDirection { get; set; }
        }
    
        public class Request
        {
            [JsonPropertyName("data")]
            public Data data { get; set; }
        }
    
        public class Total
        {
            [JsonPropertyName("volumeNumbers")]
            public VolumeNumbers volumeNumbers { get; set; }
        }
    
        public class TrafficData
        {
            [JsonPropertyName("volume")]
            public Volume volume { get; set; }
        }
    
        public class Volume
        {
            [JsonPropertyName("byHour")]
            public ByHour byHour { get; set; }
        }
    
        public class VolumeNumbers
        {
            [JsonPropertyName("volume")]
            public int volume { get; set; }
        }
    }
    

    Using your tool, I also created a Response.cs like this :

    using System.Text.Json.Serialization;
    
    namespace Something.Answers
    {
        public class Datum
        {
            [JsonPropertyName("from")]
            public DateTime from { get; set; }
    
            [JsonPropertyName("to")]
            public DateTime to { get; set; }
    
            [JsonPropertyName("heading")]
            public string heading { get; set; }
    
            [JsonPropertyName("volume")]
            public int volume { get; set; }
        }
    
        public class Result
        {
            [JsonPropertyName("data")]
            public List<Datum> data { get; set; }
        }
    }
    

    In order to handle mapping between the two type of objects, I would create a MappingConfiguration like so :

    namespace Something.Mapper
    {
        public class MappingConfiguration : Profile
        {
            public MappingConfiguration()
            {
                // TEST
                CreateMap<Something.Requests.Node, Something.Answers.Datum>()
                    .ForMember(datum => datum.from, opt => opt.MapFrom(node => node.from))
                    .ForMember(datum => datum.to, opt => opt.MapFrom(node => node.to))
                    .ForMember(datum => datum.heading, opt => opt.MapFrom(node => node.byDirection.FirstOrDefault().heading))
                    .ForMember(datum => datum.volume, opt => opt.MapFrom(node => node.byDirection.FirstOrDefault().total.volumeNumbers))
                    .ReverseMap();
            }
        }
    }
    

    In my Program.cs, I would then Dependency Inject my MappingConfiguration with code below, before my "builder.Build()" :

    var mappingConfig = new MapperConfiguration(mc =>
    {
        mc.AddProfile(new MappingConfiguration());
    });
    
    IMapper mapper = mappingConfig.CreateMapper();
    builder.Services.AddSingleton(mapper);
    

    Finally, within my business class, I can do something like this:

    var jsonRequest = "{rn  "data": {rn    "trafficData": {rn      "volume": {rn        "byHour": {rn          "edges": [rn            {rn              "node": {rn                "from": "2019-10-24T12:00:00+02:00",rn                "to": "2019-10-24T13:00:00+02:00",rn                "byDirection": [rn                  {rn                    "heading": "North",rn                    "total": {rn                      "volumeNumbers": {rn                        "volume": 696rn                      }rn                    }rn                  },rn                  {rn                    "heading": "South",rn                    "total": {rn                      "volumeNumbers": {rn                        "volume": 726rn                      }rn                    }rn                  }rn                ]rn              }rn            },rn            {rn              "node": {rn                "from": "2019-10-24T13:00:00+02:00",rn                "to": "2019-10-24T14:00:00+02:00",rn                "byDirection": [rn                  {rn                    "heading": "North",rn                    "total": {rn                      "volumeNumbers": {rn                        "volume": 805rn                      }rn                    }rn                  },rn                  {rn                    "heading": "South",rn                    "total": {rn                      "volumeNumbers": {rn                        "volume": 751rn                      }rn                    }rn                  }rn                ]rn              }rn            }rn          ]rn        }rn      }rn    }rn  }rn}";
    Something.Requests.Request myRequest = JsonSerializer.Deserialize<Something.Requests.Request>(jsonRequest);
    
    List<Something.Answers.Datum> data= new List<Something.Answers.Datum>();
    
    foreach(var edge in myRequest.data.trafficData.volume.byHour.edges)
    {
         var tmp = _mapper.Map<Something.Requests.Node>(edge.node);
    }
    var jsonAnswer = JsonSerializer.Serialize(data);
    

    Hope this gives you an alternative.

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