2

I had this JSON string from server previously

"[
 {
    \"name":\"XYZ",
    \"age\":\"75\",
    \"height\":\"170.1\",
    \"weight\":\"69.6\",
    \"dob\":\"2000-10-07T07:23:26.876Z\"
 },
 {
    \"name":\"ABC",
    \"age\":\"15\",
    \"height\":\"160.1\",
    \"weight\":\"55.6\",
    \"dob\":\"1990-10-07T07:23:26.876Z\"
 },
]"

for which I used a class like this

   public class Person
   {
      [JsonProperty("name")]
      public string Name {get; set;}
      [JsonProperty("age")]
      public decimal Age {get; set;}
      [JsonProperty("height")]
      public decimal Height {get; set;}
      [JsonProperty("weight")]
      public decimal Weight {get; set;}
      [JsonProperty("dob")]
      public DateTime DOB {get; set;}   
   }

and I've deserialized it using

    JsonConvert.DeserializeObject<Person[]>(jsonString)

But now the server changed the JSON to be like this

"{
    \"XYZ":
    {
        \"age\":\"75\",
        \"height\":\"170.1\",
        \"weight\":\"69.6\",
        \"DOB\":\"2000-10-07T07:23:26.876Z\"
    },
    \"ABC":
    {
        \"age\":\"15\",
        \"height\":\"160.1\",
        \"weight\":\"55.6\",
        \"DOB\":\"1990-10-07T07:23:26.876Z\"
    }
}"

The name property was removed and instead it became the root element. I tried changing the class to be like this but it's not working. How do I deserialize it?

    public class PersonResult
    {
        public Person [] Persons {get; set;}
    }
jps
  • 20,041
  • 15
  • 75
  • 79
Questions
  • 195
  • 1
  • 14
  • 2
    If you had that string from the server, it looks double encoded. If you pulled that text out of your debugger after getting it from the server, be careful you don't go down the rabbithole of trying to remove backslashes that aren't actually there, they were jsut inserted by the debugger display tooltip in VS – Caius Jard Oct 07 '21 at 08:32
  • You're right, I copied the string from the debugger. – Questions Oct 07 '21 at 10:08

1 Answers1

2
string jsonString = @"{
    ""XYZ"":
    {
        ""age"":""75"",
        ""height"":""170.1"",
        ""weight"":""69.6"",
        ""DOB"":""2000-10-07T07:23:26.876Z""
    },
    ""ABC"":
    {
        ""age"":""15"",
        ""height"":""160.1"",
        ""weight"":""55.6"",
        ""DOB"":""1990-10-07T07:23:26.876Z""
    }
}";

// deserialize
var data = JsonConvert.DeserializeObject<Dictionary<string, Person>>(jsonString);
// fixup
foreach (var (key, value) in data)
{
    value.Name = key;
}
// display
foreach (var (key, value) in data)
{
    Console.WriteLine($"{value.Name}, {value.Age}");
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Could also use `.Select(..)` on the dictionary to map it to the previous `Person[]` directly. – Squirrelkiller Oct 07 '21 at 09:20
  • This worked perfectly. I wonder if there's any other way to do this and avoid making lot of changes to the current code. – Questions Oct 07 '21 at 10:18
  • Show us what lot of changes you need to make to the current code.. Perhaps we can turn this into an extension method that you can use anywhere you find your wonky json – Caius Jard Oct 07 '21 at 10:36
  • @CaiusJard This code is part of a wrapper for API, so if the current model of Person is changed (from array to dictionary), there'll be changes related to UI and business logic like populating the datagridview, search etc. And this is not the only API where the schema has changed. – Questions Oct 07 '21 at 11:34
  • 1
    Marc's answer was intended to show you how you can cope with the JSON change, but it's down to you to integrate it in a way that makes sense for your app. You aren't tied to changing anything to a dictionary.. If you have a method right now that is like `public Person[] TurnApiResponseIntoPaersonArray(string json)` then you don't have to change that to `public Dictionary<...> TurnApiResponseIntoPersonDictionary(string json)` and ripple the changes up the tree, you just make the method return e.g. `data.Values.ToArray()` after performing Marc's fixup on it.The Dictionary never leaves the method – Caius Jard Oct 07 '21 at 11:39
  • 1
    ..it's just an interim step to help you reshape the data. If you want an array out of your dictionary, you transform again. This is what I was referring to earlier about telling us more about how many different places its used in.. If there are many, then the process will always be the same: you will deser to a `Dictionary` then you will copy the dictionary entry's `Key` into `X`'s property `Y`. That's the *process* and it can be described in a *generic* way; this code can be written once and made to work for anything where you have that problem of the JSON going from array to dict – Caius Jard Oct 07 '21 at 11:40
  • @CaiusJard That's a nice idea to convert the dictionary to array and keep the existing code. I'll work on that and try to keep the changes minimal. – Questions Oct 07 '21 at 12:21
  • Feel free to ask again if you get stuck (and can reference this Q for context), questions aren't on (much) of a ration! – Caius Jard Oct 07 '21 at 12:53