How to deserialize a json array with unfixed name in JSON.NET - c#

I have a question on how to deserialize a json array with unfixed name, for instance I have a json string as below.
[
{
"37414": "MP",
"weight": 1000
},
{
"21253": "Develper",
"weight": 424
},
{
"66344": "APP",
"weight": 1158
},
{
"1622": "API",
"weight": 164
}
]
I also defines a class as below and want to use JSON.NET to deserialize json string to UserTag object. Or should I change the class definition.
public class UserTag
{
// "37414"
public long Id { get; set; }
// MP
public string Name { get; set; }
// 424
public long Weight { get; set; }
}
Thanks in advance!

Are you using correct json format ?
I think you should use:
[
{
"Id" :37414,
"Name" : "MP",
"Weight": 1000
},
{
"Id" :21253,
"Name" : "Develper",
"Weight": 424
},
{
"Id": 66344,
"Name" : "APP",
"Weight": 1158
}
]
It will deserialize to:
public class UserTag
{
public int Id { get; set; }
public string Name { get; set; }
public int Weight { get; set; }
}

var result = JsonConvert.DeserializeObject<List<Dictionary<string, string>>>(json);
foreach (var item in result)
{
foreach (var kv in item)
{
Console.WriteLine(kv.Key + ": " + kv.Value);
}
}

Related

Updating an Array of Object inside a Array of Object using linq in c#

I have a JSON object like below,
[
{
"BatchId": "BAT1",
"PartialBatch": [
{
"PartialBatchID": "PAR1",
"Status": "Active"
},
{
"PartialBatchID": "PAR2",
"Status": "Inactive"
}
]
},
{
"BatchId": "BAT2",
"PartialBatch": [
{
"PartialBatchID": "PAR3",
"Status": "Active"
},
{
"PartialBatchID": "PAR4",
"Status": "Inactive"
}
]
}
]
I have another Array of Strings of PartialBatchID's
["PAR1","PAR3"]
What would be the best and most quickiest way to update the status fields to Active for the PartialBatchID's present in above array, against the main json.
Here's a way using the Newtonsoft.Json Nuget package. Now in your example the PAR1 and PAR3 are already active, but this will work:
void Main()
{
var match = new [] { "PAR1", "PAR3"};
var json = JsonConvert.DeserializeObject<JsonData[]>(main);
foreach (var b in json.SelectMany(x => x.PartialBatch).Where(x => match.Contains(x.PartialBatchID)))
{
b.Status = "Active";
}
var modifiedJson = JsonConvert.SerializeObject(json);
}
public class JsonData
{
public string BatchId { get; set; }
public Batch[] PartialBatch { get; set; }
}
public class Batch
{
public string PartialBatchID { get; set; }
public string Status { get; set; }
}
const string main = #"
[
{
'BatchId': 'BAT1',
'PartialBatch': [
{
'PartialBatchID': 'PAR1',
'Status': 'Active'
},
{
'PartialBatchID': 'PAR2',
'Status': 'Inactive'
}
]
},
{
'BatchId': 'BAT2',
'PartialBatch': [
{
'PartialBatchID': 'PAR3',
'Status': 'Active'
},
{
'PartialBatchID': 'PAR4',
'Status': 'Inactive'
}
]
}
]";

Deserialize JSON file with different keys

I have a json like this:
[
{ "Province1" : [
{ "name" : "city-1" },
{ "name" : "city-2" }
]
},
{ "Province2" : [
{ "name" : "city-1" },
{ "name" : "city-2" }
]
}
]
I want to deserialize it using NewtonsoftJson. I have tried this but the result is null:
public class City {
public string Name { get; set; }
}
var cities = JsonConvert.DeserializeObject<IEnumerable<KeyValuePair<string, List<City>>>(File.ReadAllText(#"jsonPath"));
How should I dersialize it to a class?
After fiddling around with it a bit, I've come up with this structure to deserialize it
class MyDeserializer
{
public static void Deserialize()
{
var json = "[{\"Province1\" : [{\"name\" : \"city-1\" }, {\"name\" : \"city-2\" }] }, {\"Province2\" : [{ \"name\" : \"city-1\" }, { \"name\" : \"city-2\" }] } ]";
var cities = JsonConvert.DeserializeObject<List<Dictionary<string, List<City>>>>(json);
Console.WriteLine(cities[0]["Province1"][0].Name);
}
}
class City
{
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
}
That gives you a dictionary for each province which seems a little unintuitive. But that's how your JSON is structured. If you want to combine all the dictionaries into one, you can do it like this
var cities = JsonConvert.DeserializeObject<List<Dictionary<string, List<City>>>>(json).SelectMany(dict => dict).ToDictionary(pair => pair.Key, pair => pair.Value);
Console.WriteLine(cities["Province1"][0].Name);
There is probably a more elegant solution to this, however this will give you a dictionary of province name with an array of city name Dictionary<string,string[]>
var dict = JArray
.Parse(input)
.Cast<JObject>()
.Select(x => x.Properties().First())
.ToDictionary(
x => x.Name,
x => x.Values().Values().Select(x => x.First.ToString()).ToArray());
I think your structure should be like this :
[
{ "Name": "Province1",
"Cities": [
{ "name": "city-1" },
{ "name": "city-2" }
]
},
{ "Name": "Province2",
"Cities": [
{ "name": "city-1" },
{ "name": "city-2" }
]
}
]
And to deserilize it :
namespace ConsoleApp2 {
public class Province {
public string Name { get; set; }
public List<City> Cities { get; set; }
}
public class City {
public string Name { get; set; }
}
public class ConsoleApp2 {
public static void Main(string[] args) {
List<Province> provinces = JsonConvert.DeserializeObject<List<Province>>(File.ReadAllText("province.json"));
}
}
}

Not getting result when deserializing json using DataContractJsonSerializer

I have following json:
{
"Australia": {
"count": 2,
"records": {
"File1.ppt": {
"id": "123456789"
},
"File2.doc": {
"id": "987654321"
}
}
},
"PDFs.zip": {
"count": 0,
"records": {}
},
"Peru": {
"count": 2,
"records": {
"File3.PPT": {
"id": "897456123"
},
"File4.PPT": {
"id": "123546789"
}
}
},
"total count": 4
}
and to deserialize the above json I have defined some classes so that I can use these classes while deserializing my json into objects and below are the classes:
namespace GEO_Batch_Creation
{
[DataContract]
class BhpIdJson
{
[DataMember(Name = "objects")]
public Dictionary<string, Country[]> Countries { get; set; }
[DataMember(Name = "total count")]
public int TotalCount { get; set; }
}
[DataContract]
class Country
{
[DataMember(Name = "count")]
public int Count { get; set; }
[DataMember(Name = "records")]
public Dictionary<string, Record> Records { get; set; }
}
[DataContract]
class Record
{
[DataMember(Name = "filename")]
public string FileName { get; set; }
[DataMember(Name = "id")]
public Dictionary<string, string> BhpId { get; set; }
}
}
But when I use following code to deserialize the json I am getting only total count.
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
// Deserialization from JSON
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(BhpIdJson));
BhpIdJson bsObj2 = (BhpIdJson)deserializer.ReadObject(ms);
}
Please suggest me where I am doing mistake.
I don't think that this JSON is in correct format. I don't know if you got this from somewhere or made for yourself, but if the last one I recommend you to change the structure.
Even in C# you cant realy create a class that has the objects and the count of the object in the same List or Array etc.
Based on your class your JSON yhould look like this:
{
"objects": [
{
"name": "Australia",
"count": 2,
"records": [
{
"fileName": "File1.ppt",
"id": "123456789"
},
{
"fileName": "File2.doc",
"id": "987654321"
}
]
}
],
"total count": 4
}
As you can see you have to add Name or something to your Country class. I hope it helped.
Edit:
You can create a list like I mentioned above but it's not a good practice I think.

Is this json format correct?

I have a json data when i'm trying to parse it returns error incorrect syntax please help me found the syntax error.
[{"isData":"Yes","Details":"[{"Id":"70","Name":"Test","FileName":"Uploaded","FileFormat":".mp4","FileType":"Video","FileDuration":"00:30:00 ","StartTime":"/Date(1372617000000)/","EndTime":"/Date(1372681771000)/","File":"2562013172331815635077778118152815.mp4"}]"}]
And this is the class that is used to serialize data, i am using javascript serializer
public enum Data
{
Yes,
No
}
public class MessageResponse()
{
public string isData { get; set; }
public string Details { get; set; }
}
List<MessageResponse> response = new List<MessageResponse>();
string strJson="[{"Id":"70","Name":"Test","FileName":"Uploaded","FileFormat":".mp4","FileType":"Video","FileDuration":"00:30:00 ","StartTime":"/Date(1372617000000)/","EndTime":"/Date(1372681771000)/","File":"2562013172331815635077778118152815.mp4"}]";
var newData = new MessageResponse
{
isData = Data.Yes.ToString(),
Details = strJson
};
response.Add(newData);
var jsonSerialiser1 = new JavaScriptSerializer();
string result = jsonSerialiser1.Serialize(response);
That's invalid JSON. The Details property is incorrectly formatted. You should remove the quotes around the value. It should be like this:
[
{
"isData": "Yes",
"Details": [
{
"Id": "70",
"Name": "Test",
"FileName": "Uploaded",
"FileFormat": ".mp4",
"FileType": "Video",
"FileDuration": "00:30:00 ",
"StartTime": "/Date(1372617000000)/",
"EndTime": "/Date(1372681771000)/",
"File": "2562013172331815635077778118152815.mp4"
}
]
}
]
or if you want Details to be a string property (representing JSON), which is kinda lame, you should properly escape the double quotes:
[
{
"isData": "Yes",
"Details": "[{\"Id\":\"70\",\"Name\":\"Test\",\"FileName\":\"Uploaded\",\"FileFormat\":\".mp4\",\"FileType\":\"Video\",\"FileDuration\":\"00: 30: 00\",\"StartTime\":\"/Date(1372617000000)/\",\"EndTime\":\"/Date(1372681771000)/\",\"File\":\"2562013172331815635077778118152815.mp4\"}]"
}
]
This structure you will be able to map to your current object model. But I would recommend you using the first approach.
Remove the " from the details data:
[{
"isData":"Yes",
"Details":
[{
"Id":"70",
"Name":"Test",
"FileName":"Uploaded",
"FileFormat":".mp4",
"FileType":"Video",
"FileDuration":"00:30:00",
"StartTime":"/Date(1372617000000)/",
"EndTime":"/Date(1372681771000)/",
"File":"2562013172331815635077778118152815.mp4"
}]
}]
Details should be of type class (i.e. user defined class) and it should hold all the properties.
public class Details
{ public int Id {get; set;} ... }
Firstly your json is invalid.
It should not have the " before and after the [ ]
[
{
"isData": "Yes",
"Details": [
{
"Id": "70",
"Name": "Test",
"FileName": "Uploaded",
"FileFormat": ".mp4",
"FileType": "Video",
"FileDuration": "00: 30: 00",
"StartTime": "/Date(1372617000000)/",
"EndTime": "/Date(1372681771000)/",
"File": "2562013172331815635077778118152815.mp4"
}
]
}
]
Secondly, your class could be improved to be:
public class MessageResponse
{
public string isData { get; set; }
public Details Details { get; set; }
}
public class Details
{
public int Id { get; set; }
public string Name { get; set; }
public string FileName { get; set; }
public string FileFormat { get; set; }
public string FileType { get; set; }
public string FileDuration { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
public string File { get; set; }
}
You would probably want to set up the correct data types though for things like Start Time etc...

Deserialize Json to Class that implements Ienumerable in Asp.net

I've below function which fetches facebook data and return it as string.
public static string GetUserNewsFeed(string strAccessToken)
{
Dictionary<string, object> PostDetail = new Dictionary<string, object>();
DateTime CreatedDateTime = DateTime.Today.AddDays(-90);
var epoch = (CreatedDateTime.ToUniversalTime().Ticks - 621355968000000000) / 10000000;
PostDetail.Add("Posts", "SELECT post_id,source_id FROM stream WHERE filter_key in (SELECT filter_key FROM stream_filter WHERE uid=me() AND type='newsfeed') and (likes.count > 0 or comments.count > 0) and created_time > " + epoch);
PostDetail.Add("PostComments", "select post_id,fromid from comment where post_id in (select post_id from #Posts)");
PostDetail.Add("PostLikes", "SELECT object_id,post_id,user_id FROM like WHERE post_id in (select post_id from #Posts)");
string Json = HttpUtility.UrlEncode(Newtonsoft.Json.JsonConvert.SerializeObject(PostDetail));
return RunFQLQuery(Json, strAccessToken);
}
Here's the code that calls this function and convert it to Jobject using Json.NET :
strFeed = FacebookAPI.GetUserNewsFeed(Convert.ToString(Session["access_token"]));
JObject objStreamData = JObject.Parse(strFeed);
var PostResponse = objStreamData.SelectToken("data[0]");
Below line deserialize it to NewsFeedPost Class :
var Posts = JsonConvert.DeserializeObject<NewsFeedPost>(PostResponse.ToString());
And below is the class :
public class NewsFeedPost
{
public string name { get; set; }
public List<Post> fql_result_set { get; set; }
}
public class Post
{
public string post_id { get; set; }
public string source_id { get; set; }
}
Now problem is when I change my NewsFeedPost class to below it throws error "Cannot deserialize JSON object into type 'BAL.NewsFeedPost'" :
public class NewsFeedPost : IEnumerable<Post>
{
public string name { get; set; }
public List<Post> fql_result_set { get; set; }
public IEnumerator<Post> GetEnumerator()
{
foreach (Post item in fql_result_set)
{
yield return item;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Below is the sample of Json Response :
{
"data": [
{
"name": "Posts",
"fql_result_set": [
{
"post_id": "1"
},
{
"post_id": "2"
}
]
},
{
"name": "PostComments",
"fql_result_set": [
{
"post_id": "3",
"fromid": 4
},
{
"post_id": "5",
"fromid": 6
}
]
},
{
"name": "PostLikes",
"fql_result_set": [
{
"object_id": 7,
"post_id": "8",
"user_id": 9
},
{
"object_id": 10,
"post_id": "11",
"user_id": 12
}
]
}
]
}
I just want to enumerate through list and create comma delimited list and save it to db. Can anybody throw some light what needs to be done? How can I get the Count and Length Property for List?
Two things:
1) Add JsonObjectAttribute to NewsFeedPost:
[JsonObject]
public class NewsFeedPost : IEnumerable<Post>
2) To deserialize that JSON which you show, you need another class:
public class NewsFeedPosts
{
public List<NewsFeedPost> Data { get; set; }
}
and then you'd call your deseralize with that class as what you want deserialized:
var Posts = JsonConvert.DeserializeObject<NewsFeedPosts>(PostResponse.ToString());
You may want to try a cast on the DeserializeObject
var Posts = JsonConvert.DeserializeObject<NewsFeedPost>((NewsFeedPost)PostResponse.ToString());

Categories