I'm trying to retrieve all data from a JSON file to my C# application.
But now the problem is that the field "info" in my json file is sometimes from the type string but it can also be the type object.
{
[
{
"id":"147786",
"canUpdate":true,
"canDelete":true,
"canArchive":true,
"hasChildren":false,
"info": "Test"
},
{
"id":"147786",
"canUpdate":true,
"canDelete":true,
"canArchive":true,
"hasChildren":false,
"info": [{"id"="1","messages":"true"}]
}
]
}
well my model you can see here below, when there are only strings in my json file i can retrieve the data without any exception but when there are also objects in the info field then i get the error can't convert the value.
Is there a way to fix this on an easy way?
public string id { get; set; }
public string canUpdate { get; set; }
public string info { get; set; }
As an option you can define the info as dynamic:
public dynamic info { get; set; }
Example
Consider the following json string:
string json = #"
[
{ 'P1': 'X', 'P2': 'Y' },
{ 'P1': 'X', 'P2': [
{'P11':'XX', 'P22':'YY'},
{'P11':'XX', 'P22':'YY'}]
}
]";
You can define such model to deserialize it:
public class C
{
public string P1 { get; set; }
public dynamic P2 { get; set; }
}
And deserialize it like this:
var obj = JsonConvert.DeserializeObject<C[]>(json);
Note
If the number of dynamic properties is too much then usually there is no point in creating the class and the following code will be enough:
var obj = (dynamic)JsonConvert.DeserializeObject(json);
Related
This is the JSON im receiving, already filtered. (its coming from the google places autocomplete API)
{
"predictions": [
{
"description": "Frankfurt am Main, Deutschland",
"place_id": "ChIJxZZwR28JvUcRAMawKVBDIgQ",
},
{
"description": "Frankfurt (Oder), Deutschland",
"place_id": "ChIJb_u1AiqYB0cRwDteW0YgIQQ",
},
{
"description": "Frankfurt Hahn Flughafen (HHN), Lautzenhausen, Deutschland",
"place_id": "ChIJX3W0JgQYvkcRWBxGlm6csj0",
}
],
"status": "OK"
}
And I need to get this JSON into this format:
{
"success":true,
"message":"OK",
"data":[
{
"description":"Frankfurt Hahn Flughafen (HHN), Lautzenhausen, Deutschland",
"id":"ChIJX3W0JgQYvkcRWBxGlm6csj0"
},
{
"description":"Frankfurt Airport (FRA), Frankfurt am Main, Deutschland",
"id":"ChIJeflCVHQLvUcRMfP4IU3YdIo"
},
{
"description":"Frankfurt Marriott Hotel, Hamburger Allee, Frankfurt am Main, Deutschland",
"id":"ChIJdag3xFsJvUcRZtfKqZkzBAM"
}
]
}
I would be very g
So predictions is just renamed to "data", we change rename status to message, move it up and add a success if the http-request that happened earlier was a success or not. This does not seem so hard on the first catch, but I can't seem to find resources to transform or rearrange JSON in C#.
I would be very grateful for any tips or resources, so I can get unstuck on this probably not so difficult task. I should mention I'm fairly new to all of this.
Thank you all in advance!
First create classes thats represent your jsons
public class Prediction
{
public string description { get; set; }
public string place_id { get; set; }
}
public class InputJsonObj
{
public Prediction[] predictions { get; set; }
public string status { get; set; }
}
public class Datum
{
public string description { get; set; }
public string id { get; set; }
}
public class OutPutJsoObj
{
public bool success { get; set; }
public string message { get; set; }
public List<Datum> data { get; set; }
public OutPutJsoObj(){
data = new List<Datum>();
}
}
Then mapped objects (manually or using any of mapping libraries like AutoMapper) and create final json.
using Newtonsoft.Json;
InputJsonObj inputObj = JsonConvert.DeserializeObject<InputJsonObj >(inputJson);
OutPutJsoObj outObj = new OutPutJsoObj ();
foreach(var p in inputObj)
{
outObj.Data.Add(new Datum() { descriptions = p.descriptions , id= p.place_id }
}
string outJson = = JsonConvert.SerializeObject(outObj);
Just parse the origional json and move the data to the new json object
var origJsonObj = JObject.Parse(json);
var fixedJsonObj = new JObject {
new JProperty("success",true),
new JProperty("message",origJsonObj["status"]),
new JProperty("data",origJsonObj["predictions"])
};
it is not clear from your question what should be a success value, but I guess maybe you need this line too
if (fixedJsonObj["message"].ToString() != "OK") fixedJsonObj["success"] = false;
if you just need a fixed json
json = fixedJsonObj.ToString();
or you can create c# class (Data for example) and deserilize
Data result= fixedJsonObj.ToObject<Data>();
I like the answer from #Serge but if you're looking for a strongly typed approach we can model the input and output structure as the same set of classes and the output structure is similar, with the same relationships but only different or additional names this try this:
The process used here is described in this post but effectively we create write-only properties that will receive the data during the deserialization process and will format it into the properties that are expected in the output.
public class ResponseWrapper
{
[JsonProperty("success")]
public bool Success { get;set; }
[JsonProperty("message")]
public string Message { get;set; }
[Obsolete("This field should not be used anymore, please use Message instead")]
public string Status
{
get { return null; }
set
{
Message = value;
Success = value.Equals("OK", StringComparison.OrdinalIgnoreCase);
}
}
[JsonProperty("data")]
public Prediction[] Data { get;set; }
[Obsolete("This field should not be used anymore, please use Data instead")]
public Prediction[] Predictions
{
get { return null; }
set { Data = value; }
}
}
public class Prediction
{
public string description { get; set; }
public string place_id { get; set; }
}
Then you can deserialize and re-serialize with this code:
using Newtonsoft.Json;
...
var input = JsonConvert.DeserializeObject<ResponseWrapper>(input);
var output = JsonConvert.SerializeObject(objs, new JsonSerializerSettings
{
Formatting = Newtonsoft.Json.Formatting.Indented,
NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore
});
This is a fiddle you can test with: https://dotnetfiddle.net/DsI5Yc
And the output:
{
"success": true,
"message": "OK",
"data": [
{
"description": "Frankfurt am Main, Deutschland",
"place_id": "ChIJxZZwR28JvUcRAMawKVBDIgQ"
},
{
"description": "Frankfurt (Oder), Deutschland",
"place_id": "ChIJb_u1AiqYB0cRwDteW0YgIQQ"
},
{
"description": "Frankfurt Hahn Flughafen (HHN), Lautzenhausen, Deutschland",
"place_id": "ChIJX3W0JgQYvkcRWBxGlm6csj0"
}
]
}
If you were going to go to the trouble of writing a converter for the deserialization then I find this solution is a bit simpler. I tend to use this type of solution when exposing additional properties to allow legacy data to map into a the current code base.
keeps the mapping and logic contained within the class
tells developers still writing code against the deprecated structures about the change
You can also augment this and implement a global converter to omit obsolete properties which would give you full backwards compatibility until you update the source to stop sending the legacy structure. This is a fiddle of such a solution: https://dotnetfiddle.net/MYXtGT
Inspired by these posts:
JSON.Net Ignore Property during deserialization
Is there a way to make JavaScriptSerializer ignore properties of a certain generic type?
Exclude property from serialization via custom attribute (json.net)
Json.NET: Conditional Property Serialization
so I have a problem:
The code in JSON that you see there is a response that a webpage gives me. And the thing I want to do is really simple:
I just want to parse for example the "user_id", or "class".
I tried few things on stackoverflow that I found but no one works...
{
"data": {
"user": {
"class": "user",
"user_id": "81046537",
"etp_guid": "76411082-73ab-5aaa-9242-0bb752cf97a4",
},
},
}
Thanks !
There are many ways you can extract the user_id from the json. The most common way is to use Newtonsoft.Json package.
Assuming the json is stored as a string, you can call JObject.Parse().
var data = "{'data': {'user': {'class': 'user','user_id': '81046537','etp_guid': '76411082-73ab-5aaa-9242-0bb752cf97a4'} } }";
JObject jObject = JObject.Parse(data);
var userId = jObject["data"]["user"]["user_id"];
Console.WriteLine($"User id {userId}");
If your json is stored as a n object, then call JObject jObject = new JObject(data)
A preferred way is to serialise your json using business object. Simply create classes to match the json structure. e.g:
public class Response
{
public Data Data { get; set; }
}
public class Data
{
public User User { get; set; }
}
public class User
{
public string Class { get; set; }
public string User_id { get; set; }
public string Etp_guid { get; set; }
}
Then deserialize your object. e.g:
var response = JsonConvert.DeserializeObject<Response>(data);
Console.WriteLine($"User id {response.Data.User.User_id}");
...and "beautiful" is sarcastic here.
When you call Active Campaign's list_view endpoint, and would like to get that in a json response, then this is the json response you get:
{
"0": {
"id": "4",
"name": "Nieuwsletter 1",
"cdate": "2018-11-22 03:44:19",
"private": "0",
"userid": "6",
"subscriber_count": 2901
},
"1": {
"id": "5",
"name": "Newsletter 2",
"cdate": "2018-11-22 05:02:41",
"private": "0",
"userid": "6",
"subscriber_count": 2229
},
"2": {
"id": "6",
"name": "Newsletter 3",
"cdate": "2018-11-22 05:02:48",
"private": "0",
"userid": "6",
"subscriber_count": 638
},
"result_code": 1,
"result_message": "Success: Something is returned",
"result_output": "json"
}
Now how would I ever be able to deserialize this to an object? Doing the normal Edit => Paste Special => Paste JSON As Classes gives me an output where I end up with classes that named _2.
Also, JsonConvert throws the following error: Accessed JObject values with invalid key value: 2. Object property name expected. So it is not really able to deserialize it either. I tried to use dynamic as object type to convert to.
The only thing I can think of now is replacing the first { by [ and the last } by ], then remove all the "1" : items and then remove the last 3 properties. After that I have a basic array which is easy convertable. But I kind of hope someone has a better solution instead of diving deep into the string.indexOf and string.Replace party...
If your key/value pair is not fixed and data must be configurable then Newtonsoft.json has one feature that to be used here and that is [JsonExtensionData]. Read more
Extension data is now written when an object is serialized. Reading and writing extension data makes it possible to automatically round-trip all JSON without adding every property to the .NET type you’re deserializing to. Only declare the properties you’re interested in and let extension data do the rest.
In your case key/value pair with 0,1,2,3.......N have dynamic data so your class will be
So create one property that collects all of your dynamic key/value pair with the attribute [JsonExtensionData]. And below I create that one with name DynamicData.
class MainObj
{
[JsonExtensionData]
public Dictionary<string, JToken> DynamicData { get; set; }
public int result_code { get; set; }
public string result_message { get; set; }
public string result_output { get; set; }
}
And then you can deserialize your JSON like
string json = "Your json here"
MainObj mainObj = JsonConvert.DeserializeObject<MainObj>(json);
Edit:
If you want to collect your dynamic key's value to class then you can use below the class structure.
class MainObj
{
[JsonExtensionData]
public Dictionary<string, JToken> DynamicData { get; set; }
[JsonIgnore]
public Dictionary<string, ChildObj> ParsedData
{
get
{
return DynamicData.ToDictionary(x => x.Key, y => y.Value.ToObject<ChildObj>());
}
}
public int result_code { get; set; }
public string result_message { get; set; }
public string result_output { get; set; }
}
public class ChildObj
{
public string id { get; set; }
public string name { get; set; }
public string cdate { get; set; }
public string _private { get; set; }
public string userid { get; set; }
public int subscriber_count { get; set; }
}
And then you can deserialize your JSON like
MainObj mainObj = JsonConvert.DeserializeObject<MainObj>(json);
And then you can access each of your deserialized data like
int result_code = mainObj.result_code;
string result_message = mainObj.result_message;
string result_output = mainObj.result_output;
foreach (var item in mainObj.ParsedData)
{
string key = item.Key;
ChildObj childObj = item.Value;
string id = childObj.id;
string name = childObj.name;
string cdate = childObj.cdate;
string _private = childObj._private;
string userid = childObj.userid;
int subscriber_count = childObj.subscriber_count;
}
I'd recommend JObject from the Newtonsoft.Json library
e.g. using C# interactive
// Assuming you've installed v10.0.1 of Newtonsoft.Json using a recent version of nuget
#r "c:\Users\MyAccount\.nuget\.nuget\packages\Newtonsoft.Json\10.0.1\lib\net45\Newtonsoft.Json.dll"
using Newtonsoft.Json.Linq;
var jobj = JObject.Parse(File.ReadAllText(#"c:\code\sample.json"));
foreach (var item in jobj)
{
if (int.TryParse(item.Key, out int value))
{
Console.WriteLine((string)item.Value["id"]);
// You could then convert the object to a strongly typed version
var listItem = item.Value.ToObject<YourObject>();
}
}
Which outputs:
4
5
6
See this page for more detail
https://www.newtonsoft.com/json/help/html/QueryingLINQtoJSON.htm
Here is the Json data that I got
{
"Data": {
"namelist": [
{
"name": "Elson Mon",
"Information": {
"Age": 45.0,
"Height": 168.7,
"Weight": 75.4,
"Birthdate": "1992-03-03"
},
"Married Status": "Single"
}
]
}
}
And here are my models
public class Information
{
public double Age { get; set; }
public double Height { get; set; }
public double Weight { get; set; }
public string Birthdate { get; set; }
}
public class Namelist
{
public string name { get; set; }
public Information Information { get; set; }
public string MarriedStatus { get; set; }
}
public class Data
{
public List<Namelist> namelist { get; set; }
}
public class RootObject
{
public Data Data { get; set; }
}
How can I deserialize the Json format string and assign into variable ?
I'm trying to use
dynamic jsonResponse = JsonConvert.DeserializeObject<RootObject>(json);
to deserialize the Json data but have totally no idea on how to assign it into different variable.
Am I right in assuming your problem is actually assigning the result to a variable?
If that's the case, you needn't bother figuring out the type (although it's pretty obvious here - you're deserializing a string into RootObject, so if this works, you'll naturally have a RootObject). Just let the compiler do it for you:
var jsonResponse = JsonConvert.DeserializeObject<RootObject>(json);
You can then hover over "var" to see the type. It's much more convenient when you really have no idea what you're working with or if the type is something rather ugly like IEnumerable<KeyValuePair<int, List<string>>>.
Avoid the dynamic type in such cases; always prefer putting the actual type or "var". The compiler doesn't know what you've got if you store it in a dynamic, so it won't issue any warnings if you're using your object in an inappropriate way, you'll face the consequences run-time.
You are in the right path.
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
Example:
public static void Main(string[] args)
{
string json = #"{
'Data': {
'namelist': [
{
'name': 'Elson Mon',
'Information': {
'Age': 45.0,
'Height': 168.7,
'Weight': 75.4,
'Birthdate': '1992-03-03'
},
'Married Status': 'Single'
}
]
}
}";
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
}
I'm trying to parse the following json array
[
{
"email": "john.doe#sendgrid.com",
"timestamp": 1337197600,
"smtp-id": "<4FB4041F.6080505#sendgrid.com>",
"event": "processed"
},
{
"email": "john.doe#sendgrid.com",
"timestamp": 1337966815,
"smtp-id": "<4FBFC0DD.5040601#sendgrid.com>",
"category": "newuser",
"event": "clicked"
},
{
"email": "john.doe#sendgrid.com",
"timestamp": 1337969592,
"smtp-id": "<20120525181309.C1A9B40405B3#Example-Mac.local>",
"event": "processed"
}
]
I've not really used json format before, so it's all a little new. I found I can parse a single element easily, i.e.
{
"email": "john.doe#sendgrid.com",
"timestamp": 1337197600,
"smtp-id": "<4FB4041F.6080505#sendgrid.com>",
"event": "processed"
}
dynamic stuff = JsonConvert.DeserializeObject(json);
Response.Write(string.Format("{0} = {1}<br />", "timestamp", stuff.timestamp));
//etc
But i'm struggling with how to get the individual elements into an array to loop through.
I though about splitting the sting on },{ but didn't have much luck with that. I imagine there's an easier way i'm missing.
Thank you.
Just deserialize the JSON as is and loop it...
dynamic stuff = JsonConvert.DeserializeObject(json);
foreach (var s in stuff)
{
Console.WriteLine(s.timestamp);
}
Fiddle: http://dotnetfiddle.net/0SthDp
You can create a class like this one, to accept all properties from the json string:
public class MyClass
{
public string email { get; set; }
public long timestamp { get; set; }
[JsonProperty("smtp-id")]
public string smtpid { get; set; }
public string category { get; set; }
[JsonProperty("event")]
public string evt { get; set; }
}
As you can notice there is JsonProperty attribute on the smtpid and evt properties, because you can not use the names in the json string as properties in C#.
Then just call the following line:
var list = JsonConvert.DeserializeObject<List<MyClass>>(json);
and you'll get a strongly typed list of objects that matches the json string.
Use JSON.Net to do this for you:
Create a class to hold the data (notice the attribute I put on smtp-id to handle characters C# doesn't like):
public class EmailEvent
{
public string Email { get; set; }
public int TimeStamp { get; set; }
[Newtonsoft.Json.JsonProperty(PropertyName="smtp-id")]
public string SmtpId { get; set; }
public string Event { get; set; }
public string Category { get; set; }
}
Then just deserialize it:
var events = Newtonsoft.Json.JsonConvert.DeserializeObject<List<EmailEvent>>(System.IO.File.ReadAllText(#"z:\temp\test.json"));
foreach (var ev in events)
{
Console.WriteLine(ev.SmtpId);
}
Create these two classes to hold your data:
public class SMTPEvent {
public string Email { get; set; }
public long TimeStamp { get; set; }
public string SmtpId { get; set; }
public string EventType { get; set; }
}
public class SMTPEvents {
public List<SMTPEvent> Events { get; set; }
}
Then you can call the following:
dynamic stuff = JsonConvert.DeserializeObject<SMTPEvents>(json);
To iterate you can then use:
foreach(SMTPEvent sEvent in stuff)
{
//whatever you want to do.
}
The advantage to this approach is having more type safety at run-time whilst having reusable objects if you're going to use them in other parts of your system. If not, you might want to use the simpler dynamic approach as suggested by others.
Also, remember to use the JsonProperty attribute to specify the actual property name as specified in your JSON string if you cannot / are not going to create fields that have the exact name as in your JSON.
The first level - stuff - is an Array of objects. It is the objects, or elements in said array, which contain a timestamp field.
Consider the following:
dynamic items = JsonConvert.DeserializeObject(json);
foreach(dynamic item in items) {
/* use item.timestamp */
}