0

My JSON object consists of consistent attributes udid, date, event_id and varying but known attributes inside parameters. Below there are two objects:

      {
        "udid": "70baf33f-f011-44ee-b35a-6064b5ab468d",
        "date": "2018-01-01",
        "event_id": 2,
        "parameters": {
          "gender": "male",
          "age": 13,
          "country": "India"
        }
      },
      {
        "udid": "70baf33f-f011-44ee-b35a-6064b5ab468d",
        "date": "2018-01-01",
        "event_id": 1,
        "parameters": {}
      }

Such JSON can be represented inside one object, if I move parameters on the top level like that:

public class Event
{
    [Key]
    public int Id { get; set; }
    public string udid { get; set; }
    public DateTime date { get; set; }
    public int event_id { get; set;}
    public string gender { get; set; }
    public int age { get; set; }
    public string country { get; set; }
    public int stage { get; set; }
    public bool win { get; set; }
    public int time { get; set; }
    public int income { get; set; }
    public string name { get; set; }
    public double price { get; set; }
    public string item { get; set; }
}

So, how do I deserialize that in efficient way, because I have like 30 millions of such records? I'm using newtonsoft.json.


Edit:

I end up creating three objects (nested Parameters inside EventNested) and flattened Event as Liam adviced. I casually deserialized json into EventNested and then remapped it into Event using this bulky LINQ expression:

List<EventNested> eventsNested = JsonConvert.DeserializeObject<List<EventNested>>(json);
List<Event> events = eventsNested.Select(x=> new Event {
        date = x.date,
        udid = x.udid,
        event_id = x.event_id,
        parametersAge = x.Parameters.age,
        parametersCountry = x.Parameters.country, 
        parametersGender = x.Parameters.gender, 
        parametersIncome = x.Parameters.income,
        parametersItem = x.Parameters.item, 
        parametersName = x.Parameters.name,
        parametersPrice = x.Parameters.price, 
        parametersStage = x.Parameters.stage,
        parametersTime = x.Parameters.time, 
        parametersWin = x.Parameters.win
    } ).ToList();
Maksym
  • 35
  • 7
  • Possible duplicate of [Generically Flatten Json using c#](https://stackoverflow.com/questions/32782937/generically-flatten-json-using-c-sharp) – Crowcoder May 19 '19 at 11:13

1 Answers1

0

Just nest one object inside the other. (If you're using EF, maybe it would be better to have 2 separate Events: one for your DbSet (without nested object) and another as a JSON data contract.)

public class Event
{
    //.. the rest of your attributes here
    public EventParameters Parameters { get; set; }

}

public class EventParameters
{
    public int? Age { get; set; } // If such parameter may not exist in your JSON, ensure it to be nullable in your POCO.
    public string Country { get; set; }
    public string Gender { get; set; }
}
Liam Kernighan
  • 2,335
  • 1
  • 21
  • 24
  • The problem is that if I want to get access to EventParameters from Events, I have to include it with `Events.include(x=>x.EventParameters).ToList()` and that will require about 20 times more RAM. Also I'm using BulkInsert and it works best without nested object. Maybe I'm doing something wrong, so correct me – Maksym May 19 '19 at 11:23
  • 1
    I would do that that way, if you don't want to have a separate table for parameters in your DbContext: 1. Create three Classes: a flat DbSet for your event and a JsonEvent with JsonEventParameters inside it. 2. Map one to another before save (either via AutoMapper or just manually) – Liam Kernighan May 19 '19 at 11:27
  • 1
    Ah, thank you. I just tried messing up with automapper for the first time, thought it will be faster. But I gave up and stuck to LINQ mapping and turns out it works fast. So, your solution with 3 objects works best – Maksym May 19 '19 at 12:42