Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deserialize JSON with variable property names

Tags:

json

c#

json.net

I would like to desierialze the json from here.

Similar to this:

{
"BW": {
    "Neujahrstag": {
        "datum": "2017-01-01",
        "hinweis": ""
    },
    "Heilige Drei K\u00f6nige": {
        "datum": "2017-01-06",
        "hinweis": ""
    },
    "Gr\u00fcndonnerstag": {
        "datum": "2017-04-13",
        "hinweis": "Gem\u00e4\u00df \u00a7 4 Abs. 3 des Feiertagsgesetzes von Baden-W\u00fcrttemberg[10] haben Sch\u00fcler am Gr\u00fcndonnerstag und am Reformationstag schulfrei. In der Regel legt das Kultusministerium die Ferientermine so fest, dass diese beiden Tage in die Osterferien bzw. in die Herbstferien fallen."
    },
    "Karfreitag": {
        "datum": "2017-04-14",
        "hinweis": ""
    }
},
"BY": {
    "Neujahrstag": {
        "datum": "2017-01-01",
        "hinweis": ""
    },
    "Heilige Drei K\u00f6nige": {
        "datum": "2017-01-06",
        "hinweis": ""
    }
}

}

I would like to deserialize into this:

public class Root
{
    public State[] States { get; set; }
}

public class State
{        
    public Holiday[] Holidays { get; set; }
}

public class Holiday
{
    public DateTime Date { get; set; }
    public string Note { get; set; }
}

But since the propertynames are not fixed I am not able to do this.

I've also tried using JObject.Parse() but that did not help me alot.

Any idea on how to do this ?

like image 309
Felix D. Avatar asked Nov 27 '17 09:11

Felix D.


People also ask

What does JsonConvert DeserializeObject do?

DeserializeObject Method. Deserializes the JSON to a . NET object.

How do I deserialize a JSON file?

A common way to deserialize JSON is to first create a class with properties and fields that represent one or more of the JSON properties. Then, to deserialize from a string or a file, call the JsonSerializer. Deserialize method.

What is JsonProperty annotation C#?

JsonPropertyAttribute indicates that a property should be serialized when member serialization is set to opt-in. It includes non-public properties in serialization and deserialization. It can be used to customize type name, reference, null, and default value handling for the property value.


2 Answers

If you modify your model to this:

public class Root : Dictionary<string, State> { }

public class State : Dictionary<string, Holiday> { }

public class Holiday {
    [JsonProperty(PropertyName = "datum")]
    public DateTime Date { get; set; }

    [JsonProperty(PropertyName = "hinweis")]
    public string Note { get; set; }
}

You can deserialize using this:

var root = JsonConvert.DeserializeObject<Root>(str);
var firstBwHoliday = root["BW"]?["Neujahrstag"].Date;
like image 152
K. H. Avatar answered Nov 07 '22 04:11

K. H.


First update the Holiday to handle the property names

public class Holiday {
    [JsonProperty("datum")]
    public DateTime Date { get; set; }
    [JsonProperty("hinweis")]
    public string Note { get; set; }
}

Next you want to deserialize to nested Dictionaries

var rawRoot = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, Holiday>>>(json);

Finally you want to traverse the dictionaries to get your final result

var root = new Root {
    States = rawRoot.Select(stateKvp => new State() {
        Holidays = stateKvp.Value.Select(holidayKvp => holidayKvp.Value).ToArray()
    })
    .ToArray()
};

You do however loose the keys as they were not part of your final model.

like image 35
Nkosi Avatar answered Nov 07 '22 02:11

Nkosi