Deserializing JSON with an empty value that was serialized as {} - c#

I'm using the Newtonsoft Json Converter to serialize and deserialize objects and it works great for my program.
But if any of the values stored within the object are null/empty, they are serialized as {}, unable to be deserialized, and my program stops.
For example, if I deserialize the following code, everything works great:
{
"Thing1": 2,
"Thing2": false,
"Thing3": "string",
"Thing4": "2017-10-28T14:04:24.74"
}
But if I try to deserialize the following code:
{
"Thing1": {},
"Thing2": false,
"Thing3": "",
"Thing4": {}
}
Thing1 and Thing4 will both cause problems during deserialization.
Not sure if this could be related to the way I am reading from my database to serialize:
var r = Serialize(myReader);
string json = JsonConvert.SerializeObject(r,
Formatting.Indented,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
public IEnumerable<Dictionary<string, object>> Serialize(SqlDataReader reader)
{
var results = new List<Dictionary<string, object>>();
var cols = new List<string>();
for (var i = 0; i < reader.FieldCount; i++)
cols.Add(reader.GetName(i));
while (reader.Read())
results.Add(SerializeRow(cols, reader));
return results;
}
private Dictionary<string, object> SerializeRow(IEnumerable<string> cols,
SqlDataReader reader)
{
var result = new Dictionary<string, object>();
foreach (var col in cols)
result.Add(col, reader[col]);
return result;
}
I've used:
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }
Within my deserializer:
BlankObject blnkObj = JsonConvert.DeserializeObject<BlankObject>(json, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
How can I deserialize an empty value? Thanks in advance.

You need to have a class structure like following:
public class RootObject
{
public object Thing1 { get; set; }
public bool Thing2 { get; set; }
public string Thing3 { get; set; }
public object Thing4 { get; set; }
}

Figured out my problem thanks to the comment by #dbc
An object of null value is serialized as {} in JSON instead of null
The deserializer did not like deserializing {} into an int. Because a null object is of a different type than an int or DateTime.
My solution was to serialize the results of the database to have null instead of {} by reading from the database like this:
BlankClass test = new BlankClass();
string json = "";
if (myReader.Read())
{
test.Thing1 = (int)myReader[0];
test.Thing2 = (bool)myReader[1];
test.Thing3 = (string)myReader[2];
test.Thing4 = (Datetime?)myReader[3];
json = JsonConvert.SerializeObject(test, Formatting.Indented);
}
class BlankClass
{
int Thing1 { get; set; }
bool Thing2 { get; set; }
string Thing3 { get; set; }
DateTime? Thing4 { get; set; }
}

Related

Json Deserializing not populating properties

I'm deserializing a third party string like this:
{"status":4,"errors":[{"Duplicate Application":"Duplicate Application"}]}
I use my standard extension method:
public static T DeserializeJson<T>(string response)
where T : class
{
var s = new DataContractJsonSerializer(typeof(T));
try {
using (var ms = new MemoryStream()) {
byte[] data = System.Text.Encoding.UTF8.GetBytes(response);
ms.Write(data, 0, data.Length);
ms.Position = 0;
return (T)s.ReadObject(ms);
}
}
catch {
return default(T);
}
}
The class I'm trying to deserialize to looks like this:
[DataContract]
public class ResponseProps
{
[DataMember(Name = "status", Order = 0)]
public string ResponseCode { get; set; }
[DataMember(Name = "lead_id", Order=1)]
public string LeadId { get; set; }
[DataMember(Name = "price", Order=2)]
public decimal Price { get; set; }
[DataMember(Name = "redirect_url", Order = 3)]
public string RedirectUrl { get; set; }
[DataMember(Name = "errors", Order = 4)]
public List<Dictionary<string, string>> Errors { get; set; }
}
I'm using a List of type Dictionary (string, string) for the Errors property because other types I've tried have broken the deserializer - this works in that the serializer no longer throws an exception.
However, I'm now trying to retrieve the data from Errors - I'm using this code:
var cr = XmlHelper.DeserializeJson<ResponseProps>(response);
var errorStore = new HashSet<string>();
foreach (var dict in cr.Errors)
{
foreach (var kvp in dict)
{
errorStore.Add(kvp.Key + ": " + kvp.Value);
}
}
I've done various tests - the dict counts 1, but there are no kvp, so when the loop runs I get no messages.
I'm guessing this is again down to deserialization rather than incorrect looping, but I've not been able to fix it.
Anyone got any advice?
To be able to deserialize such dictionary, you should customize settings of DataContractJsonSerializer with UseSimpleDictionaryFormat set to true:
DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings
{
UseSimpleDictionaryFormat = true
};
var s = new DataContractJsonSerializer(typeof(T), settings);
By the way, do you have any reason to use DataContractJsonSerializer with your custom DeserializeJson<T>() method? You could do the same in one line of code with JSON.Net:
var obj = JsonConvert.DeserializeObject<ResponseProps>(str);
JSON.Net is also much more flexible and have a better performance than DataContractJsonSerializer.

How to itrate JSON object?

I trying to get the id and email list from the JSON. How can i achieve this?
My JSON string is
{
"name":"name1",
"username":"name1",
"id":505,
"state":"active",
"email":"name1#mail.com",
},
{
"name":"name2",
"username":"name2",
"id":504,
"state":"active",
"email":"name2#mail.com",
}
My code is
Dictionary<string, string> engineers = new Dictionary<string, string>();
using (StreamReader r = new StreamReader(#"D:\project\Gitlap\EngineerEmail\jsonlist5.json"))
{
using (JsonTextReader reader = new JsonTextReader(r))
{
JObject o2 = (JObject)JToken.ReadFrom(reader);
string id = o2["id"].ToString();
string email = o2["email"].ToString();
engineers.Add(email, id);
}
}
class UserItems
{
public string id { get; set; }
public string email { get; set; }
}
I can able to get the first person`s mail ID and ID details. I need to iterate this JSON and get all the mail ID and ID.
I don`t know that how to iterate this JSON. I tried some method from the internet but that was not succeeded.
How can I do?
First thing is your JSON input is not valid json, you need to fix it. There are two issues in it. Its not collection of json objects and comma is missing between two objects.
Valid json should look like below.
[{
"name":"name1",
"username":"name1",
"id":505,
"state":"active",
"email":"name1#mail.com",
},
{
"name":"name2",
"username":"name2",
"id":504,
"state":"active",
"email":"name2#mail.com",
}]
Now define a c# class representing your json object.
public class User
{
public string name { get; set; }
public string username { get; set; }
public int id { get; set; }
public string state { get; set; }
public string email { get; set; }
}
Use JSON.Net library to deserialize it as shown below.
private void button1_Click(object sender, EventArgs e)
{
if(File.Exists("json1.json"))
{
string inputJSON = File.ReadAllText("json1.json");
if(!string.IsNullOrWhiteSpace(inputJSON))
{
var userList = JsonConvert.DeserializeObject<List<User>>(inputJSON);
}
}
}
JObject o2 = (JObject)JToken.ReadFrom(reader);
foreach(var obj in o2)
{
string id = obj["id"].ToString();
string Email= obj["Email"].ToString();
engineers.Add(email, id);
}
I would recommend using the Json.NET NuGet package to accomplish this.
Firstly, create a model to represent your JSON data. Typically I would capitalize the first letter of the property names here, but to keep it consistent with the JSON, they are lower case.
public class UserData
{
public string name { get; set; }
public string username { get; set; }
public int id { get; set; }
public string state { get; set; }
public string email { get; set; }
}
You will need to add a using for Json.NET
using Newtonsoft.Json;
Finally, you can load, and deserialize your data into a strongly typed list, which you can then use to populate your engineers dictionary.
string datapath = #"D:\project\Gitlap\EngineerEmail\jsonlist5.json";
Dictionary<string, string> engineers = new Dictionary<string, string>();
List<UserData> data = new List<UserData>();
using (StreamReader r = new StreamReader(datapath))
{
string json = r.ReadToEnd();
data = JsonConvert.DeserializeObject<List<UserData>>(json);
data.ForEach(engineer => engineers.Add(engineer.email, engineer.id.ToString()));
}
As mentioned in another answer, your JSON is also badly formed. This will need correcting before it will deserialize correctly. We just need to add a comma to separate the two objects, and wrap them both in a JSON array, with []
[
{
"name":"name1",
"username":"name1",
"id":505,
"state":"active",
"email":"name1#mail.com"
},
{
"name":"name2",
"username":"name2",
"id":504,
"state":"active",
"email":"name2#mail.com"
}
]
Improvements
As your Id field is an integer, it would be better to change your dictionary from
Dictionary<string, string> engineers = new Dictionary<string, string>();
into
Dictionary<string, int> engineers = new Dictionary<int, string>();
You will then be able to simplify your ForEach query slightly. The ForEach can also be moved outside of the using() block.
data.ForEach(engineer =>
engineers.Add(engineer.email, engineer.id));
Improved solution
This includes the improvements above, I've used var for brevity.
var datapath = #"D:\project\Gitlap\EngineerEmail\jsonlist5.json";
var engineers = new Dictionary<string, int>();
var data = new List<UserData>();
using (var r = new StreamReader(datapath))
{
var json = r.ReadToEnd();
data = JsonConvert.DeserializeObject<List<UserData>>(json);
}
data.ForEach(engineer =>
engineers.Add(engineer.email, engineer.id));
try to create class that represent the data in json object for example
Class obj
{
public int Id { get ; set; }
public string email { get ; set; }
public string username { get ; set; }
public string state { get ; set; }
public string email { get ; set; }
}
then
using System.Web.Script.Serialization;
var js = new JavaScriptSerializer();
List<obj> list = js.Deserialize<List<obj>>(jsonString);
after that you can access all list items id and email by using foreach

How do deserialize JSON with non-standard (and varying) property names (in .NET)

I have to read a JSON stream (which I have no control over), which is in the form:
{"files":
{
"/some_file_path.ext": {"size":"1000", "data":"xxx", "data2":"yyy"},
"/other_file_path.ext": {"size":"2000", "data":"xxx", "data2":"yyy"},
"/another_file_path.ext": {"size":"3000", "data":"xxx", "data2":"yyy"},
}
}
So, I have an object named files, which has a number of properties, which have 1) different names every time, 2) different number of them every time, and 3) names with characters which can't be used in C# properties.
How do I deserialize this?
I'm putting this into a Portable Library, so I can't use the JavaScriptSerializer, in System.Web.Script.Serialization, and I'm not sure about JSON.NET. I was hoping to use the standard DataContractJsonSerializer.
UPDATE: I've changed the sample data to be closer to the actual data, and corrected the JSON syntax in the area the wasn't important. (Still simplified quite a bit, but the other parts are fairly standard)
You can model your "files" object as a Dictionary keyed by the JSON property name:
public class RootObject
{
public Dictionary<string, PathData> files { get; set; }
}
public class PathData
{
public int size { get; set; }
public string data { get; set; }
public string data2 { get; set; }
}
Then, only if you are using .Net 4.5 or later, you can deserialize using DataContractJsonSerializer, but you must first set DataContractJsonSerializerSettings.UseSimpleDictionaryFormat = true:
var settings = new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true };
var root = DataContractJsonSerializerHelper.GetObject<RootObject>(jsonString, settings);
With the helper method:
public static class DataContractJsonSerializerHelper
{
public static T GetObject<T>(string json, DataContractJsonSerializer serializer = null)
{
using (var stream = GenerateStreamFromString(json))
{
var obj = (serializer ?? new DataContractJsonSerializer(typeof(T))).ReadObject(stream);
return (T)obj;
}
}
public static T GetObject<T>(string json, DataContractJsonSerializerSettings settings)
{
return GetObject<T>(json, new DataContractJsonSerializer(typeof(T), settings));
}
private static MemoryStream GenerateStreamFromString(string value)
{
return new MemoryStream(Encoding.Unicode.GetBytes(value ?? ""));
}
}
Alternatively, you can install Json.NET and do:
var root = JsonConvert.DeserializeObject<RootObject>(jsonString);
Json.NET automatically serializes dictionaries to JSON objects without needing to change settings.
We need to first convert this Invalid JSON to a Valid JSON. So a Valid JSON should look like this
{
"files":
{
"FilePath" : "C:\\some\\file\\path",
"FileData" : {
"size": 1000,
"data": "xxx",
"data2": "yyy"
},
"FilePath" :"C:\\other\\file\\path",
"FileData" : {
"size": 2000,
"data": "xxx",
"data2": "yyy"
},
"FilePath" :"C:\\another\\file\\path",
"FileData" : {
"size": 3000,
"data": "xxx",
"data2": "yyy"
}
}
}
To make it a valid JSON we might use some string functions to make it looks like above. Such as
MyJSON = MyJSON.Replace("\\", "\\\\");
MyJSON = MyJSON.Replace("files", "\"files\"");
MyJSON = MyJSON.Replace("data:", "\"data:\"");
MyJSON = MyJSON.Replace("data2", "\"data2\"");
MyJSON = MyJSON.Replace(": {size", ",\"FileData\" : {\"size\"");
MyJSON = MyJSON.Replace("C:", "\"FilePath\" :\"C:");
Than we can create a class like below to read the
public class FileData
{
public int size { get; set; }
public string data { get; set; }
public string data2 { get; set; }
}
public class Files
{
public string FilePath { get; set; }
public FileData FileData { get; set; }
}
public class RootObject
{
public Files files { get; set; }
}
Assuming you have a valid JSON you could use JavaScriptSerializer to return a list of objects
string json = "{}"
var serializer = new JavaScriptSerializer();
var deserializedValues = (Dictionary<string, object>)serializer.Deserialize(json, typeof(object));
Alternatively you could specify Dictionary<string, List<string>> as the type argument
strign json = "{}";
JavaScriptSerializer serializer = new JavaScriptSerializer();
var deserializedValues = serializer.Deserialize<Dictionary<string, List<string>>>(json);
foreach (KeyValuePair<string, List<string>> kvp in deserializedValues)
{
Console.WriteLine(kvp.Key + ": " + string.Join(",", kvp.Value));
}

C# - How to parse json

I have a json string as following
string json = "{\"Method\":\"LOGIN\",\"Skill\":{\"1\":\"SKILL-1\",\"2\":\"SKILL-2\"}}";
I am using JavaScriptSerializer to parse json
System.Web.Script.Serialization.JavaScriptSerializer oSerializer =
new System.Web.Script.Serialization.JavaScriptSerializer();
var dict = oSerializer.Deserialize<Dictionary<string,object>>(json);
I am getting Method = LOGIN using following line
MessageBox.Show("Method = "+dict["Method"].ToString());
But how to get Skill in a loop. like
Skill
1 = SKILL-1
2 = SKILL-2
The value mapping to your Skill key is actually another Dictionary<string, object>. You can iterate it by casting the object:
string json = "{\"Method\":\"LOGIN\",\"Skill\":{\"1\":\"SKILL-1\",\"2\":\"SKILL-2\"}}";
var oSerializer = new JavaScriptSerializer();
var dict = oSerializer.Deserialize<Dictionary<string,object>>(json);
var innerDict = dict["Skill"] as Dictionary<string, object>;
if (innerDict != null)
{
foreach (var kvp in innerDict)
{
Console.WriteLine ("{0} = {1}", kvp.Key, kvp.Value);
}
}
Or, the alternative would be to map your object into a proper class and deserialize to it instead of a generic Dictionary<string, object>.
Suppose you have following class
public class Data
{
public string Method { get; set; }
public Skills Skill { get; set; }
// If you don't want to use Skills class then you can use this
//public Dictionary<int, string> Skills { get; set; }
}
public class Skills
{
public int Id { get; set; }
public string Skill { get; set; }
}
So you can Deserialize json into Data Object like this
Data deserializedData = JsonConvert.DeserializeObject<Data>(json);
You should declare your own class:
public class YourClassName
{
public string Method { get; set; }
public Dictionary<int, string> Skill { get; set; }
}
and deserialize the Json string like this:
var obj = oSerializer.Deserialize<YourClassName>(json);

Deserialize JSON into string

How can I deserialize:
{
"data": [
{"ForecastID":8587961,"StatusForecast":"Done"},
{"ForecastID":8588095,"StatusForecast":"Done"},
{"ForecastID":8588136,"StatusForecast":"Done"},
{"ForecastID":8588142,"StatusForecast":"Pending"}
]
}
to
class RawData
{
public string data { get; set; }
}
So, I just want to have
[
{"ForecastID":8587961,"StatusForecast":"Done"},
{"ForecastID":8588095,"StatusForecast":"Done"},
{"ForecastID":8588136,"StatusForecast":"Done"},
{"ForecastID":8588142,"StatusForecast":"Pending"}
]
as value of property data of RawData's class instance.
Using Json.Net
var obj = (JObject)JsonConvert.DeserializeObject(json);
var newJson = obj["data"].ToString();
or using built-in JavaScriptSerializer
var dict = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
var newjson = new JavaScriptSerializer().Serialize(dict["data"]);
It would have made far much more sense to deserialize this JSON structure to:
public class Forecast
{
public IEnumerable<ForecastData> Data { get; set; }
}
public class ForecastData
{
public int ForecastID { get; set; }
public string StatusForecast { get; set; }
}
which is pretty trivial with the JavaScriptSerializer class that's built into the framework:
string json = "your JSON data here";
IEnumerable<ForecastData> data = new JavaScriptSerializer()
.Deserialize<Forecast>(json)
.Data;
or if you don't want to define models you could do that:
dynamic result = new JavaScriptSerializer().DeserializeObject(json);
foreach (var item in result["data"])
{
Console.WriteLine("{0}: {1}", item["ForecastID"], item["StatusForecast"]);
}

Categories

Resources