Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialize JSON to 2 different models

Tags:

json

c#

json.net

Does Newtonsoft.JSON library have a simple way I can automatically deserialize JSON into 2 different Models/classes?

For example I get the JSON:

[{
  "guardian_id": "1453",
  "guardian_name": "Foo Bar",
  "patient_id": "938",
  "patient_name": "Foo Bar",
}]

And I need de-serialize this to the following models:

class Guardian {

  [JsonProperty(PropertyName = "guardian_id")]
  public int ID { get; set; }

  [JsonProperty(PropertyName = "guardian_name")]
  public int Name { get; set; }
}


class Patient {

  [JsonProperty(PropertyName = "patient_id")]
  public int ID { get; set; }

  [JsonProperty(PropertyName = "patient_name")]
  public int Name { get; set; }
}

Is there a simple way to deserialize this JSON into 2 Models without having to iterate over the JSON? Maybe JSON property ids will just work?

Pair<Guardian, Patient> pair = JsonConvert.DeserializeObject(response.Content);
like image 543
sazr Avatar asked Apr 04 '18 08:04

sazr


3 Answers

First off, your models are slightly incorrect. The name properties need to be strings, instead of integers:

class Guardian
{

    [JsonProperty(PropertyName = "guardian_id")]
    public int ID { get; set; }

    [JsonProperty(PropertyName = "guardian_name")]
    public string Name { get; set; }            // <-- This
}


class Patient
{

    [JsonProperty(PropertyName = "patient_id")]
    public int ID { get; set; }

    [JsonProperty(PropertyName = "patient_name")]
    public string Name { get; set; }            // <-- This
}

Once you've corrected that, you can deserialize the JSON string into two lists of different types. In your case, List<Guardian> and List<Patient> respectively:

string json = @"[{'guardian_id':'1453','guardian_name':'Foo Bar','patient_id':'938','patient_name':'Foo Bar'}]";
var guardians = JsonConvert.DeserializeObject<List<Guardian>>(json);
var patients = JsonConvert.DeserializeObject<List<Patient>>(json);
like image 80
Nisarg Shah Avatar answered Oct 10 '22 01:10

Nisarg Shah


It can't be done with 1 call with the types that you show. You can try using the generic <T> approach for each type, also you'll need to use arrays or lists for the return type because the source JSON is an array:

var guardians = JsonConvert.DeserializeObject<Guardian[]>(response.Content);
var patients = JsonConvert.DeserializeObject<Patient[]>(response.Content);

And then combine the two if you need them to be paired. E.g. if you are sure that you always have just one of each:

var pair = new Pair(guardians[0], patients[0]);
like image 43
Peter B Avatar answered Oct 10 '22 00:10

Peter B


Not in one call, and it seems the data is an array, so you need a little more work.

Zip is the key method here to join the two separate object lists:

Guardian[] guardians = JsonConvert.DeserializeObject<Guardian[]>(response.Content);
Patient[] patients = JsonConvert.DeserializeObject<Patient[]>(response.Content);

var combined = guardians.Zip(patients, (g, p) => Tuple.Create(g, p)).ToList();

It would be far more easier to just read the JSON at once, it a single object.

like image 33
Patrick Hofman Avatar answered Oct 10 '22 00:10

Patrick Hofman