Parse json nested array into c# object - c#

I´m need to parse a json object into a c# class, my problem is that json object has a nested array and it´s throwing some errors when parsing.
I have tried a couple of options:
a) do foreach in the elements of nested array, and add them to a new array
b) parsing using json.deserialize
No success so far
These are my c# classes
public class itemPrediccion
{
public string ClavePartido { get; set; }
public string Ganador { get; set; }
public bool EsFavorito { get; set; }
}
public class Prediccion
{
public ObjectId _id { get; set; }
public string IdUsuario { get; set; }
public int Jornada { get; set; }
public IEnumerable<itemPrediccion> PrediccionesJornada { get; set; }
}
An object of class "Prediccion" would contain a list of "itemPrediccion"
This is the json object that I want to parse to a "Prediccion" object
{
"IdUsuario" : "user1",
"Jornada" : "1",
"PrediccionesJornada" : [
{
"ClavePartido" : "AP2019J1P1",
"Ganador": "Morelia",
"EsFavorito": "false"
},
{
"ClavePartido" : "AP2019J1P2",
"Ganador": "Chivas",
"EsFavorito": "false"
},
{
"ClavePartido" : "AP2019J1P3",
"Ganador": "Atlas",
"EsFavorito": "true"
}
]
}
This is how I´m trying to deserialize
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
Prediccion prediccionUsuario = new Prediccion {
IdUsuario = data.IdUsuario,
Jornada = data.Jornada,
PrediccionesJornada = data.PrediccionesJornada
};
Throws this error:
Cannot implicitly convert type 'Newtonsoft.Json.Linq.JArray' to
'System.Collections.Generic.IEnumerable'.
An explicit conversion exists (are you missing a cast?)

You should be able to use the non dynamic variant of the deserializer:
var result =JsonConvert.DeserializeObject<Prediccion>(requestBody);

Related

Reading and Writing Nested data JSON in C#

I have looked at several solutions over the web on reading nested json files but I haven't found one suitable to my need. Maybe because I am new to JSON. Here is my issue:
I have the following JSON in a file:
{
"ConfigError" : {
"DateSent": "2022-04-28T14:03:16.6628493-07:00",
"ToolType": "WSM",
"IsSent": true
},
"FileCopyError" : {
"DateSent": "2022-06-14T14:03:16.6628493-07:00",
"ToolType": "RMT",
"IsSent": false
}
}
For this I have written two classes. One for the Inner object:
public class SummaryEmailStatus
{
public DateTime DateSent { get; set; }
public string ToolType { get; set; }
public bool IsSent { get; set; }
}
One for the Outer Objects:
public class SummaryEmailClass
{
SummaryEmailStatus Status { get; set; } = new SummaryEmailStatus();
}
I would like to be able to read the JSON in C#. I'm primarily concerned with the inner objects. They are of same class but they need to be used differently. So ideally I'd want a function that I can pass in "ConfigError" or "FileCopyError" into and it will return SummaryEmailStatus class object populated by the values in the JSON:
public static void ReadJasonFile(string jsonFileName, string objctName)
{
List<SummaryEmailClass> emailClassList = new List<SummaryEmailClass>();
dynamic jsonFile = JsonConvert.DeserializeObject(File.ReadAllText(jsonFileName));
SummaryEmailStatus sumclass = jsonFile[objctName];
}
But this gives me a run time error saying:
Cannot implicitly convert type "Newtonsoft.Json.Linq.JObject to SummaryEmailStatus
How can I successfully parse out the inner summaryemailstatus objects?
Additionally, I'd like to be able to create the JSON data within C#. The reason being, when I read the JSON, I will do some task and then will need to update the values of the JSON with the current timestamps. I'd imagine, I'd need to rewrite the file. How can I write a nested JSON like this in C#?
If JSON is not the best way to do this, I am open to alternatives
you can try
string json = File.ReadAllText(jsonFileName);
Dictionary<string,SummaryEmailStatus> summaryEmailStatus =
JsonConvert.DeserializeObject<Dictionary<string,SummaryEmailStatus>>(json);
you can use it
SummaryEmailStatus configError = summaryEmailStatus["ConfigError"];
if you want update data
summaryEmailStatus["ConfigError"].DateSent= DateTime.Now;
and serialize back
json = JsonConvert.SerializeObject(summaryEmailStatus);
or if you have only 2 main properties, create a class
public class SummaryEmailClass
{
SummaryEmailStatus ConfigError { get; set; }
SummaryEmailStatus FileCopyError{ get; set; }
}
and use it
SummaryEmailClass summaryEmailStatus =
JsonConvert.DeserializeObject<SummaryEmailStatusClass>(json);
SummaryEmailStatus configError = summaryEmailStatus.ConfigError;
Summary
You need to convert your JObject into the type you are expecting, as shown here:
SummaryEmailStatus sumclass = jsonFile[objctName].ToObject<SummaryEmailStatus>();
Details
jsonFile[objtName] is of type JObject. The reason is because JsonConvert.DeserializeObject has no idea that you intend to convert that into a list of SummaryEmailStatus.
Once you have your array of JObjects, you can convert that into a SummaryEmailStatus as shown in the following snippet:
public static void ReadJasonFile(string jsonFileName, string objctName)
{
List<SummaryEmailClass> emailClassList = new List<SummaryEmailClass>();
dynamic jsonFile = JsonConvert.DeserializeObject(File.ReadAllText(jsonFileName));
SummaryEmailStatus sumclass = jsonFile[objctName].ToObject<SummaryEmailStatus>();
}
Easy way is kept both objects in JSON, I rewrite your code and add root. For example, if you want to write Config Error and don't write File Copy Error, you can save one of them like null.
public class ConfigError
{
public DateTime DateSent { get; set; }
public string ToolType { get; set; }
public bool IsSent { get; set; }
}
public class FileCopyError
{
public DateTime DateSent { get; set; }
public string ToolType { get; set; }
public bool IsSent { get; set; }
}
public class Root
{
public ConfigError ConfigError { get; set; }
public FileCopyError FileCopyError { get; set; }
}
//in your method to get all data
var json = File.ReadAllText(jsonFileName);
var myDeserializedClass = JsonConvert.DeserializeObject<Root>(json);
Example change config and write to file
var json = #"{
""ConfigError"" : {
""DateSent"": ""2022-04-28T14:03:16.6628493-07:00"",
""ToolType"": ""WSM"",
""IsSent"": true
},
""FileCopyError"" : {
""DateSent"": ""2022-06-14T14:03:16.6628493-07:00"",
""ToolType"": ""RMT"",
""IsSent"": false
}
}";
var conf = JsonConvert.DeserializeObject<Root>(json);
conf.ConfigError.DateSent = DateTime.Now;
conf.ConfigError.ToolType = "New way";
conf.ConfigError.IsSent = false;
conf.FileCopyError = null;
var newJson = JsonConvert.SerializeObject(conf);
File.WriteAllText("your path", newJson);

Using Jsonseralizer when the value comes across with 'Null'

I have a json string I am trying to serialize into an object, but some of the values are 'null', not null as in empty, but actually the word null, unfortunately those are not string values. I attempted to add the defaultignorecondition whenwritingnull, but that alone doesn't seem to work. The error is:
InvalidOperationException: Cannot get the value of a token type 'Null' as a number
My code:
var settings = new JsonSerializerOptions
{
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull
};
gdata = JsonSerializer.Deserialize<List<gasData>>(response.Content, settings);
Example from the json raw data:
"no_offset":0.0000,"no_units":"ppb","so2_sensor_serial_number":null,"so2_state":"Not Fitted","so2_prescaled":null
Try this code, it is working properly
var json = "{\"no_offset\":0,\"no_units\":\"ppb\",\"so2_sensor_serial_number\":null,\"so2_state\":\"Not Fitted\",\"so2_prescaled\":null}";
var data = System.Text.Json.JsonSerializer.Deserialize<Data>(json);
class
public partial class Data
{
[JsonPropertyName("no_offset")]
public long? NoOffset { get; set; }
[JsonPropertyName("no_units")]
public string NoUnits { get; set; }
[JsonPropertyName("so2_sensor_serial_number")]
public long? So2SensorSerialNumber { get; set; }
[JsonPropertyName("so2_state")]
public string So2State { get; set; }
[JsonPropertyName("so2_prescaled")]
public object So2Prescaled { get; set; }
}

LINQ to JSON - Newtonsoft.Json.Linq.JProperty Error

The following is my json string:
string json = #"{
'?xml' : {
'#version' : '1.0',
'#encoding' : 'UTF-8'
},
'DataFeed' : {
'#FeedName' : 'AdminData',
'Issuer' : {
'id' : '95',
'name' : 'Apple',
'symbol' : 'AAPL'
}
}
}";
When I try to do the following LINQ query:
JObject feed = JObject.Parse(json);
var compInfo = feed["DataFeed"]["Issuer"]
.Select(c => c["name"]);
I get the following error:
`Cannot access child value on Newtonsoft.Json.Linq.JProperty.`
However, the following works fine:
var test1 = feed["DataFeed"]["Issuer"]["name"];
Any idea why I can't use LINQ on this json string?
Think about what your JSON is. You're selecting from a dictionary so the result in the LINQ is the property. You're trying to then access "name" on a property which doesn't make sense which gives you the error.
You already have the working code:
var test1 = feed["DataFeed"]["Issuer"]["name"];
You can get the value you want using two methods:
Method 1:
First you need a cast from JToken to a JObject since the value of 'Issuer' is an object:
var compInfo = (JObject)feed["DataFeed"]["Issuer"];
Then loop through all the properties to find the one with the name "Name" then get its value as a string:
var str = compInfo.Properties().First(x => x.Name == "name").ToObject<string>();
// str will contain the value 'Apple'.
Method 2:
You can also deserialize the JSON into an object that is easier to handle. To do that first you'll need to create a .net object "equivalent" of your JSON . You can use Visual Studio to generate these for you from the Edit menu -> Paste Special -> Paste JSON as classes or use a website like JsonUtils.com
public class Xml
{
[JsonProperty("#version")]
public string Version { get; set; }
[JsonProperty("#encoding")]
public string Encoding { get; set; }
}
public class Issuer
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("symbol")]
public string Symbol { get; set; }
}
public class DataFeed
{
[JsonProperty("#FeedName")]
public string FeedName { get; set; }
[JsonProperty("Issuer")]
public Issuer Issuer { get; set; }
}
public class RootJsonObject
{
[JsonProperty("?xml")]
public Xml Xml { get; set; }
[JsonProperty("DataFeed")]
public DataFeed DataFeed { get; set; }
}
Then all you have to do to get the Issuer name is this:
var feed = JsonConvert.DeserializeObject<RootJsonObject>(json);
var issuer = feed.DataFeed.Issuer.Name;

write data from JSON in C#

I have JSON like this:
{
'surveys': [
{
'title': 'first',
'id': 100,
},
{
'title': 'second',
'id': 101,
},
{
'title': 'third',
'id': 102,
},
]
}
I want to have the output like this:
title: first
title: second
title: third
and my program in C# is like this:
WebClient client = new WebClient();
var json = client.DownloadString("http://www.test.com/api/surveys/?api_key=123");
Debug.WriteLine(json); //write all data from json
//add
var example = JsonConvert.DeserializeObject<Example>(json);
Debug.WriteLine(example.Data.Length);
class Example
{
public surveys[] Data { get; set; }
}
class surveys
{
public string title { get; set; }
public int id { get; set; }
}
I get this error:
Thrown: "Object reference not set to an instance of an object." (System.NullReferenceException) Exception Message = "Object reference not set to an instance of an object.", Exception Type = "System.NullReferenceException", Exception WinRT Data = ""
at this line: Debug.WriteLine(example.Data.Length);
where is the problem?
One problem I see is that your outer class has a property named Data, which is an array of 'surveys' objects, but your Json has a list of 'surverys' objects under the property 'surveys'. Hence the 'Data' property is never populated.
Consider the following C# class structure:
class Example
{
public survey[] surveys{ get; set; }//Data renames to surveys
}
class survey //Singular
{
public string title { get; set; }
public int id { get; set; }
}
Why can't you do so?:
JObject data = JObject.Parse(json);
foreach (var survey in data["surveys"].Children())
{
Debug.WriteLine("title: " + survey["title"]);
}
You need to use JSON.Net and use the class JsonConvert and the method DeserializeObject<T>.
If you run this:
JsonConvert.DeserializeObject<JObject>();
Then you will get back a list of de-serialized JObject objects.
Use, NuGet to download the package. I think it is called JSON.net.
Here is the weblink
WebClient client = new WebClient();
var json = client.DownloadString("http://www.test.com/api/surveys/?api_key=123");
Debug.WriteLine(json); //write all data from json
//add
var example = JsonConvert.DeserializeObject<Survey>(json);
Debug.WriteLine(example.length); // this could be count() instead.
class Survey
{
public string title { get; set; }
public int id { get; set; }
}
This should work!
Use json2csharp to generate c# classes from json.
You will also need to use Json.NET.
public class Survey
{
public string title { get; set; }
public int id { get; set; }
}
public class RootObject
{
public List<Survey> surveys { get; set; }
}
Then you can do:
var client = new WebClient();
string json = client.DownloadString(some_url);
RootObject root = JsonConvert.DeserializeObject<RootObject>(json);
foreach (Survey s in root.surveys)
{
// Do something with your survey
}
Don't forget to use Newtonsoft.Json namespace once you add a reference to it within your project.
using Newtonsoft.Json;
Edit: I have tested it using:
string json = "{'surveys': [{'title': 'first','id': 100,},{'title': 'second','id': 101,},{'title': 'third','id': 102,},]}";
instead of using the WebClient, and it works.

JavaScriptDeseializer : Can not serialize array

My application is asp.net. I have to send some values back to server. For this I create a object serialize it and send it to server. At server I try to de-serialize it
Following is my code
[Serializable]
public class PassData
{
public PassData()
{
}
public List<testWh> SelectedId { get; set; }
public string SelectedControlClientId { get; set; }
public string GroupTypeId { get; set; }
public string SectionTypeId { get; set; }
}
[Serializable]
public class testWh
{
public testWh()
{
}
public string Id { get; set; }
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
//this can not serialize the SelectedId and the count remains 0
PassData data = serializer.Deserialize<PassData>(jsonString);
//this serialize in an anonymous object with key value pair
var data2 = serializer.DeserializeObject(textHiddenArguments.Text);
Following is my Json Serialized String
{
"SelectedId":{"0":"ABCD","1":"JKLM"},
"SelectedControlClientId":"YTUTOOO",
"GroupTypeId":3,
"SectionTypeId":"1"
}
quotes escaped string
"{\"SelectedId\":{\"0\":\"ABCD\",\"1\":\"JKLM\"},\"SelectedControlClientId\":\"YTUTOOO\",\"GroupTypeId\":3,\"SectionTypeId\":\"1\"}"
My Problem is Selected Id is array of testWH object. But when I try to desrialize it, the SelectedId property of PassData which is list does not get serialized and count remains zero.
I tried using array instead of List, which gave an exception "no parameter less constructor..."
Could any one explain the what I am doing wrong here ?
The key problem here is that the JSON doesn't match the objects you have constructed. You can see this by writing the data you want and serializing:
var obj = new PassData
{
SelectedId = new List<testWh>
{
new testWh { Id = "ABCD"},
new testWh { Id = "JKLM"}
},
GroupTypeId = "3",
SectionTypeId = "1",
SelectedControlClientId = "YTUTOOO"
};
string jsonString = serializer.Serialize(obj);
which gives JSON like:
{"SelectedId":[{"Id":"ABCD"},{"Id":"JKLM"}],
"SelectedControlClientId":"YTUTOOO","GroupTypeId":"3","SectionTypeId":"1"}
So now you need to decide which you want to change; the JSON or the classes. The following alternative class works fine with your original JSON, for example:
public class PassData
{
public Dictionary<string,string> SelectedId { get; set; }
public string SelectedControlClientId { get; set; }
public string GroupTypeId { get; set; }
public string SectionTypeId { get; set; }
}

Categories