I have this Json:
{
"UpdatePack":"updatePacks\/1585654836.pack",
"Updates":[
{
"Name":"MsgBoxEx",
"version":"1.5.14.88",
"ChangeLog":"BugFix: Form didn't resize correct.",
"Hash":"5FB23ED83693A6D3147A0485CD13288315F77D3D37AAC0697E70B8F8C9AA0BB8"
},
{
"Name":"Utilities",
"version":"2.5.1.58",
"ChangeLog":"StringManagement updated.",
"Hash":"05E6B3F521225C604662916F50A701E9783E13776DE4FCA27BE4B69705491AC5"
}
]
}
I have created 2 classes to be used to Deserialize it.
class UpdatesList
{
public string Name { get; set; }
public string Version { get; set; }
public string ChangeLog { get; set; }
public string Hash { get; set; }
}
class JsonObjectHolder
{
public string UpdatePack { get; set; }
//public Dictionary<int, MyData> { get; set; }
public Dictionary<int, UpdatesList> Updates { get; set; }
}
But when I try to access the dictionary, I keep getting Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object. at " Console.WriteLine(jsonTest.Dict.Count);"
Am I Deserializing it wrong, or do I need to do some thing else to access the result of the dictionary?
I'm new to both C# and Json.
I hope that some one could point me in the right direction on how to handle this.
I'm using Visual Studio 2019 latest update, and .net 4.8. Regards /LR
JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).
Newtonsoft. Json uses reflection to get constructor parameters and then tries to find closest match by name of these constructor parameters to object's properties. It also checks type of property and parameters to match. If there is no match found, then default value will be passed to this parameterized constructor.
deserialize() , you must specify the type of value you expect the JSON to yield, and Apex will attempt to deserialize to that type. JSON. serialize() accepts both Apex collections and objects, in any combination that's convertible to legal JSON. String jsonString = JSON.
You code doesn't work because 0
and 1
tokens just a properties, not the array items (you don't have square brackets []
around them). You can parse these values to desired structure manually using JObject
var json = JObject.Parse(your_json_string);
var dict = new Dictionary<int, UpdatesList>();
foreach (var item in json.Properties())
{
if (item.Value.Type == JTokenType.Object)
{
var index = int.Parse(item.Name);
var updateList = item.Value.ToObject<UpdatesList>();
dict.Add(index, updateList);
}
}
var holder = new JsonObjectHolder
{
UpdatePack = json["Updates"]?.Value<string>(),
Dict = dict
};
Update: According to OP changes made to JSON it might be deserialized even more simply
var list = json["Updates"]?.ToObject<List<UpdatesList>>();
var holder = new JsonObjectHolder
{
UpdatePack = json["UpdatePack"]?.Value<string>(),
Dict = list.Select((updatesList, index) => new { updatesList, index })
.ToDictionary(x => x.index, x => x.updatesList)
};
The main point here is that Updates
is an array of items, not the key-value collection. It can be transformed into Dictionary<int, UpdatesList>
using ToDictionary
method from System.Linq
(or just use List<UpdatesList>
as is)
The exception you're getting essentially means the value is being accessed before the object is initialized.
A better, simpler and cleaner way to doing it is using NewtonSoft. (you can easily get it as a Nuget package)
example:
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public IList<string> Roles { get; set; }
}
and then usage:
string json = @"{
'Email': '[email protected]',
'Active': true,
'CreatedDate': '2013-01-20T00:00:00Z',
'Roles': [
'User',
'Admin'
]
}";
Account account = JsonConvert.DeserializeObject<Account>(json);
Console.WriteLine(account.Email);
Source: https://www.newtonsoft.com/json/help/html/DeserializeObject.htm
I don't see why you need Dictionary<int, UpdatesList> Updates
, when you can easily just use List<Update> Updates
, since your updates are in a JSON array.
I would model your classes like this:
public class Update
{
public string Name { get; set; }
public string Version { get; set; }
public string ChangeLog { get; set; }
public string Hash { get; set; }
}
public class RootObject
{
public string UpdatePack { get; set; }
public List<Update> Updates { get; set; }
}
You can then deserialize with:
JsonConvert.DeserializeObject<RootObject>(json);
Try it out on dotnetfiddle.net
Note: To convert JSON to C# classes, you can go to Edit -> Paste Special -> Paste JSON as Classes inside Visual Studio. Make sure you have copied the JSON to your clipboard before using it. You will get classes similar to above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With