Parse Json Array with different of keyvalue - c#

In one of my project i want to parse a JSON array with different key name. For Example
{ "details": [
{ "state": "myState1",
"place": [
{ "name": "placeName" } ] },
{ "state": "myState2",
"place": [
{ "name1": "placeName" } ] },
{ "state": "myState3",
"place": [
{ "name2": "placeName" } ] } }
So in this JSON please look at the place array. each time key like name1,name2,name3...,
.And also it is not necessary to get the same JSON at all the time. In some time only state1 or state1 and state3 and in some time state1 to state 50.
So how can i identify and parse exact data from this array

First of all your JSON is not well-formatted. You miss a closing square bracket ] before the last closing curly bracket }.
Then, you can't parse variable-name properties to a static class, but you can turn them into a dictionary. Here's an example of mapping classes that work with variable places:
public class Details
{
public string state { get; set; }
public List<Dictionary<string, string>> place { get; set; }
}
public class Wrap
{
public Details[] details { get; set; }
}
static void Main(string[] args)
{
string txt = File.ReadAllText("MyJSONFile.txt");
JavaScriptSerializer ser = new JavaScriptSerializer();
var data = ser.Deserialize<Wrap>(txt);
}
If also the place property will change name, I think the simplest way to parse it is to use the following, very loosely typed, class:
public class Wrap
{
public List<Dictionary<string,object>> details { get; set; }
}
where the object in the dictionary will be a string or a dictionary of properties according to the values in the JSON.

Related

I need to rearrange a JSON but I cant find a solution

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

Deserialize Active campaign's beautiful json output to c# object

...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

Avoid serialization of a property name in json.net

How to avoid a property name during serialization? Below an example
public class A {
public List<object> Values { get; set; }
public string Name { get; set; }
}
A a = new A();
a.Name = "Numbers"
a.Values = new List<object>();
a.Values.Add(1);
a.Values.Add(2);
a.Values.Add(3);
a.Values.Add(4);
JsonConvert.SerializeObject(new { a });
After serialization, result includes a property names "values"
{
"a": {
"values": [
1,
2,
3,
4
],
"name": "Numbers"
}
}
but, I need the following
{
"a": [
1,
2,
3,
4
],
"name": "Numbers"
}
Just serialize a.Values;
JsonConvert.SerializeObject(a.Values);
You have a couple mistakes in your code.
First, if you want this class:
public class A
{
public List<object> Values { get; set; }
public string Name { get; set; }
}
To serialize to this json:
{
"a": [
1,
2,
3,
4
],
"name": "Numbers"
}
You are gonna have a bad time. Just look at the structure, they are not 1-1.
You need to change your class, make sure you name it something meaningful (a class of a single letter is a really bad idea).
public class SomeClass
{
[JsonProperty("a")]
public List<object> Values { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
You notice the [JsonProperty()] attribute above? That tells the serializer that this property should serialize with the defined name. That way you can have a meaningful property name ("Values") while in code, and still have the json serialize the way you want it to ("a").
The second problem is when you serialize you are creating a new anonymous object with a property of the class you instance you created. Which will again mess your structure up. Change your serialization code to just serialize the object instance:
string json = JsonConvert.SerializeObject(someInstanceOfYourClass);
My above changes should give you json that looks like this:
{
"a": [
1,
2,
3,
4
],
"name": "Numbers"
}
I have made a fiddle here that will demonstrate.

Reading a JSON file into an object C#

I have a JSON list of players for a game. I need the program to be able to read the JSON file and give me the list of players. Then I can use this list of players to get each player's name and who they are following.
{
"Version": "1",
"Users": [
{
"UserName": "CoolDude",
"Following": [ "SniperElitez", "IamAwesome" ]
},
{
"UserName": "GamerChick",
"Following": [ "IamAwesome", "NoWayBro", "WowWhoMe", "SniperElitez", "SurfingIsFun", "NowUTry" ]
},
{
"UserName": "SurfingIsFun",
"Following": [ "WowWhoMe" ]
},
{
"UserName": "IamAwesome",
"Following": [ "GamerChick", "NoWayBro" ]
},
{
"UserName": "NowUTry",
"Following": [ "GamerChick", "SniperElitez" ]
},
{
"UserName": "SniperElitez",
"Following": [ "SurfingIsFun", "IamAwesome" ]
},
{
"UserName": "WowWhoMe",
"Following": [ "NoWayBro", "GamerChick", "SniperElitez" ]
},
{
"UserName": "NoWayBro",
"Following": [ "GamerChick", "IamAwesome", "SniperElitez" ]
}
]
}
Here is the code I'm trying to use currently
Player Class
class Player
{
public string UserName { get; set;}
public List<string> Following { get; set;}
}
PlayerList Class
class PlayerList
{
public List<Player> pList { get; set; }
}
Main
{
string json = File.ReadAllText("friends.json");
// this gives me a playerList object
PlayerList playerList = JsonConvert.DeserializeObject<PlayerList>(json);
}
Supposedly the PlayerList object is not null but the List is empty. If anyone can tell me how to turn the JSON into the PlayerList object and then from there, get player's variables like UserName, I would greatly appreciate it!
Visual Studio has a nice feature for parsing XML / JSON... namely, if you copy an XML or a JSON to your clipboard then you can use Edit -> Paste Special -> Paste JSON As Classes command and have VS automatically generate valid model classes.
In case of your JSON this is the output my VS generated:
public class Rootobject
{
public string Version { get; set; }
public User[] Users { get; set; }
}
public class User
{
public string UserName { get; set; }
public string[] Following { get; set; }
}
Try that.
Also, you're using JsonConvert, which appears to be something by Newtonsoft. I have no idea if it's a good library or not, but there ARE .NET classes which are capable of deserializing JSON. The linked question offers one method. Another is to use a DataContractJsonSerializer, albeit I think the model classes would need to have the [DataContract] and [DataMember] attributes added to them to work with that.
The reason is that in the json doc the attribute is called "Users" and in your code you have called it "pList".
There are two solutions to this:
Rename PlayerList.pList to PlayerList.Users
Add a JsonProperty attribute on the property to set its name like this:
class PlayerList
{
[JsonProperty(PropertyName = "Users")]
public List pList { get; set; }
}
I was able to get this working by following what was stated in the question at the following link:
How to deserialize an JObject to .NET object
Here is my code:
var playerList = JsonConvert.DeserializeObject(json);
JObject jObject = ((JObject)playerList);
PlayerList users = jObject.ToObject<PlayerList>();
I also renamed the pList to Users on the PlayerList Class.

Model to match this JSON for deserialization, field names with dashes

I am trying to create a model that would match the JSON.NET deserealization of this JSON structure:
First item...
{
"190374": {
"vid": 190374,
"canonical-vid": 190374,
"portal-id": 62515,
"is-contact": true,
"profile-token": "AO_T-mN1n0Mbol1q9X9UeCtRwUE1G2GFUt0VVxCzpxUF1LJ8L3i75x9NmhIiS0K9UQkx19bShhlUwlIujY4pSXAFPEfDG-k9n8BkbftPw6Y5oM3eU5Dc_Mm-5YNJTXiWyeVSQJAN_-Xo",
"profile-url": "https://app.hubspot.com/contacts/62515/lists/public/contact/_AO_T-mN1n0Mbol1q9X9UeCtRwUE1G2GFUt0VVxCzpxUF1LJ8L3i75x9NmhIiS0K9UQkx19bShhlUwlIujY4pSXAFPEfDG-k9n8BkbftPw6Y5oM3eU5Dc_Mm-5YNJTXiWyeVSQJAN_-Xo/",
"properties": {
"phone": {
"value": "null"
},
"hs_social_linkedin_clicks": {
"value": "0"
},
"hs_social_num_broadcast_clicks": {
"value": "0"
},
"hs_social_facebook_clicks": {
"value": "0"
},
"state": {
"value": "MA"
},
"createdate": {
"value": "1380897795295"
},
"hs_analytics_revenue": {
"value": "0.0"
},
"lastname": {
"value": "Mott"
},
"company": {
"value": "HubSpot"
}
},
"form-submissions": [],
"identity-profiles": []
},
"form-submissions": [],
"identity-profiles": []
},
**next similar entry**
Then I try to bind with List of this:
public class HubSpotEmailRqst
{
public int vid { get; set; }
public int canonical-vid { get; set; }
public int portal-id { get; set; }
public bool is-contact { get; set; }
public String profile-token { get; set; }
public String profile-url { get; set; }
public Dictionary<string, string> properties { get; set; }
public Dictionary<string,string> form-submissions { get; set; }
public Dictionary<string,string> identity-profiles { get; set; }
}
I am not sure this will bind either, but I cannot get past the fact we cannot have hyphen in the field names, how can I get around this?
There're two ways to use properties with hyphens:
Name properties according to C# rules, but decorate them with [JsonProperty("property-name")] attribute.
Use custom contract resolver which modifies property names. For example, if all properties in JSON are named consistently, you can use regex to change PascalCase C# property names to lower-case JSON property names. See CamelCasePropertyNamesContractResolver from Json.NET for example implementation.
If I'm understanding the question correctly, you are upset that you can't use a hyphen in a field name in a C# program? Why not use CamelCase to identify the fields? Instead of is-contact use 'isContact'. Instead of canonical-vid. use canonicalVid. Sure, the names may look different, but to the programmer the meaning should be clear.

Categories

Resources