Deserializing JSON with dynamic keys
Seriously, no need to go down the dynamic route; use
var deser = new JavaScriptSerializer()
.Deserialize<Dictionary<string, Dictionary<string, int>>>(val);
var justDaily = deser["daily"];
to get a dictionary, and then you can e.g.
foreach (string key in justDaily.Keys)
Console.WriteLine(key + ": " + justDaily[key]);
to get the keys present and the corresponding values.
json deserialization to C# with dynamic keys
If you are using Json.NET, you can use JsonConvert.DeserializeObject<Dictionary<string, Dataset>>(json)
and the keys of the dictionary will be nasdaq_imbalance
, DXOpen IM
, Float Shares
Parse (Deserialize) JSON with dynamic keys (C#)
you don't need to deserialize, you can parse
var jsonParsed=JObject.Parse(json);
string[] previewNames= ((JArray)jsonParsed["objects"])
.Select(v => ((JObject)v["sets"]))
.Select(i=>i.Properties().Select(y=> y.Value["preview"]["resource"])).First()
.Select(i=> (string) ((JObject)i)["preview_name"]).ToArray();
result
preview.040914
preview.81a54c
Deserialize JSON with dynamic key into Object
You are close.
In your JSON, the dynamic keys are at the root level, and so that object needs to be represented by a Dictionary<string, ISBN>
. It seems you have realized this, however, in your model, you have added an outer class to contain the dictionary. This doesn't line up with the JSON and is not needed here. Instead, you should deserialize directly into the dictionary:
string json = new WebClient().DownloadString(URLAddress);
var bookRoot = JsonConvert.DeserializeObject<Dictionary<string, ISBN>>(json);
From there, you can loop over the Values
collection on the dictionary to access the books without having to know the key(s) in advance:
foreach (var isbn in bookRoot.Values)
{
// ...
}
Or, if you're expecting only one book, you can get it from the dictionary like this:
var isbn = bookRoot.Values.First();
Here is a working demo: https://dotnetfiddle.net/csgSKp
Deserialize JSON with dynamic keys using C# Json.NET
The typical solution to dealing with dynamic keys is to use a Dictionary<string, T>
in place of a regular class. See How can I deserialize a child object with dynamic (numeric) key names? for an example of this. However, that solution doesn't really work for your case, because there are other properties in the same object which do not have dynamic keys (the bankName
and totalAmount
), and the values of those properties are primitives whereas the value of dynamic property is an array of bank accounts. A better solution here is to use a JsonConverter
.
Before we get to that, we need to set up a class structure to deserialize into. This is pretty straightforward:
class RootObject
{
public List<Bank> BankDetails { get; set; }
}
[JsonConverter(typeof(BankConverter))]
class Bank
{
public string BankName { get; set; }
public decimal TotalAmount { get; set; }
public List<Account> Accounts { get; set; }
}
class Account
{
[JsonProperty("sNo")]
public int SequenceNumber { get; set; }
[JsonProperty("acNo")]
public string AccountNumber { get; set; }
[JsonProperty("acBalance")]
public decimal Balance { get; set; }
}
You'll notice that I've added a few [JsonProperty]
attributes in the Account
class to map the shorthand property names in the JSON to friendlier property names in that class. And the [JsonConverter]
attribute on the Bank
class tells the serializer that we will be using a custom BankConverter
to handle that class.
Here is the code for the BankConverter
. It uses a JObject
internally to make it easier to read and work with the JSON.
class BankConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Bank);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject obj = JObject.Load(reader);
Bank bank = new Bank();
// populate the known properties (bankName and totalAmount)
serializer.Populate(obj.CreateReader(), bank);
// now handle the dynamic key
bank.Accounts = obj[bank.BankName].ToObject<List<Account>>(serializer);
return bank;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
With these classes in place, you can deserialize the JSON like this:
var root = JsonConvert.DeserializeObject<RootObject>(json);
Here is a working demo: https://dotnetfiddle.net/knsRLv
How to deserialize JSON with dynamic and static key names in C#
You have two options, the first is to deserialise directly to a List<Dictionary<string, object>>
, for example:
var responses = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(json);
Alternatively, if you are stuck on using your object, you will need to write a custom converter. For example, something like this:
public class MyResponseConverter : JsonConverter
{
public override bool CanConvert(Type type) => type == typeof(MyResponse);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var responseObject = JObject.Load(reader);
MyResponse response = new MyResponse
{
StartTime = (string)responseObject["starttime"],
EndTime = (string)responseObject["endtime"],
};
var varData = new Dictionary<string, object>();
foreach (var property in responseObject.Properties())
{
if(property.Name == "starttime" || property.Name == "endtime")
{
continue;
}
varData.Add(property.Name, property.Value);
}
response.VarData = varData;
return response;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// If you want to write to JSON, you will need to implement this method
throw new NotImplementedException();
}
}
And your class would change slightly to this:
[JsonConverter(typeof(MyResponseConverter))]
public class MyResponse
{
[JsonProperty(PropertyName = "starttime")]
public string StartTime { get; set; }
[JsonProperty(PropertyName = "endtime")]
public string EndTime { get; set; }
public Dictionary<string, object> VarData { get; set; }
}
Now you deserialise like this:
var responses = JsonConvert.DeserializeObject<List<MyResponse>>(json);
How to deserialize json with nest array of dynamic keys in C#
Why do you want to deserialize it as List<ModuleResult>
, when the JSON structure you've provided indicates that it is a single ModuleResult
object?
Just change
var mResults = JsonConvert.DeserializeObject<List<ModuleResult>>( jsonString );
To
var mResults = JsonConvert.DeserializeObject<ModuleResult>( jsonString );
and it will be deserialized correctly.
What C# data type would you de-serialize this Json into
You can deserialise this json into
a class which has a property T(t)ranslations
and this property is a Dictionary<string, SomeClass>
.
Related Topics
Pass-Through Mouse Events to Parent Control
Transparent Images with C# Winforms
System.Text.JSON API Is There Something Like Icontractresolver
Difference Between Invoke and Dynamicinvoke
Why Must a Lambda Expression Be Cast When Supplied as a Plain Delegate Parameter
Using C# .Net Libraries to Check for Imap Messages from Gmail Servers
@Html.Dropdownlistfor How to Set Default Value
Generic Method Executed with a Runtime Type
Access to the Path Is Denied When Using Directory.Getfiles(...)
How to Pass Parameters to Another Process in C#
Differencebetween Using Idisposable VS a Destructor in C#
Entity Framework Self Referencing Loop Detected
"Invalid JSON Primitive" in Ajax Processing
Combination of List<List<Int>>
How to Assign a Func<> Conditionally Between Lambdas Using the Conditional Ternary Operator