Json deserialize ignoring objects with wrong values - c#

I want to make my json deserializer ignore objects with improper values (like string in place of a int) or return null for them and continue to deserialize the rest of a json file.
Here is my json:
{
"requests":[
{
"clientId":"1",
"requestId":"1",
"name":"Bułka",
"quantity":"1",
"price":"10.00"
},
{
"clientId":"1",
"requestId":"2.1",
"name":"Chleb",
"quantity":"2",
"price":"15.00"
},
{
"clientId":"1",
"requestId":"2",
"name":"Chleb",
"quantity":"5",
"price":"15.00"
},
{
"clientId":"2",
"requestId":"1",
"name":"Chleb",
"quantity":"1",
"price":"10.00"
}
]
}
Here are the classes I'm deserializing to:
class RequestCollection
{
public List<Request> requests { get; set; }
public RequestCollection()
{
requests = new List<Request>();
}
}
class Request
{
public string clientId { get; set; }
public long requestId { get; set; }
public string name { get; set; }
public int quantity { get; set; }
public double price { get; set; }
public Request() { }
public Request(string clientID, long requestID, string name, int quantity, double price)
{
this.clientId = clientID;
this.requestId = requestID;
this.name = name;
this.quantity = quantity;
this.price = price;
}
}
And here is how I deserialize the file:
requestCollectionLocal = JsonConvert.DeserializeObject<RequestCollection>(json);
As you can see I have improper value of requestId in 2nd object in json file. I want the result of deserialization to be just 3 other objects or all 4 objects with null values instead of improper ones.

You can deserialize your json to anonymous type, and then filter result with linq
Define an anonymous type like
var template = new {
requests = new [] {
new {
clientId = "",
requestId = "",
name = "",
quantity = "",
price = ""
}
}
};
Here you can see that all types are string, so deserialization should work well. Now you should check that it is possible to convert each string to corresponding data type with TryParse. Full code:
var json = "{\r\n \"requests\":[\r\n {\r\n \"clientId\":\"1\",\r\n \"requestId\":\"1\",\r\n \"name\":\"Bułka\",\r\n \"quantity\":\"1\",\r\n \"price\":\"10.00\"\r\n },\r\n {\r\n \"clientId\":\"1\",\r\n \"requestId\":\"2.1\",\r\n \"name\":\"Chleb\",\r\n \"quantity\":\"2\",\r\n \"price\":\"15.00\"\r\n },\r\n {\r\n \"clientId\":\"1\",\r\n \"requestId\":\"2\",\r\n \"name\":\"Chleb\",\r\n \"quantity\":\"5\",\r\n \"price\":\"15.00\"\r\n },\r\n {\r\n \"clientId\":\"2\",\r\n \"requestId\":\"1\",\r\n \"name\":\"Chleb\",\r\n \"quantity\":\"1\",\r\n \"price\":\"10.00\"\r\n }\r\n ]\r\n}";
var template = new { requests = new [] { new {clientId = "", requestId = "", name = "", quantity = "", price = ""} }};
var tempRequestCollection = JsonConvert.DeserializeAnonymousType(json, template);
var result = new RequestCollection
{
requests = tempRequestCollection.requests
.Where(r =>
long.TryParse(r.requestId, out var _)
&& int.TryParse(r.quantity, out var _)
&& double.TryParse(r.price, out var _)
)
.Select(r => new Request
{
clientId = r.clientId,
requestId = long.Parse(r.requestId),
name = r.name,
quantity = int.Parse(r.quantity),
price = double.Parse(r.price)
})
.ToList()
};

Related

How can i get all values of JSON array

I have this JSON response:
{
"post_parameters_error_flag": false,
"data_error_flag": false,
"row_count": 7,
"message": "Operazione completata.",
"title": [
"title0",
"title1",
"title2",
"title3",
"title4",
"title5",
"title6"
],
"data": [
"value0",
"value1",
"value2",
"value3",
"value4",
"value5",
"value6",
"value7"
]
}
I need to write in a list (for example) all values obtained from 'data' array but I don't know how to get data from response:
string URL = "myurl";
string Params = string.Format("hwid={0}&building={1}", Utils.UUID(), "test");
Request HTTPRequest = new Request();
JObject JSONObject = JObject.Parse(await HTTPRequest.PostAsyncResponse(URL, Params));
//now? what can i do
Any idea to solve?
You can either use like this:
var result = await HTTPRequest.PostAsyncResponse(URL, Params)
var token = JToken.Parse(result);
var data= token.Value<JArray>("data");
Or you can also use JsonPath:
var result = await HTTPRequest.PostAsyncResponse(URL, Params)
var token = JToken.Parse(result);
var data = token.SelectTokens("$.data[*]");
But really, you should be serilizing into an object and then using the properties to get the data (or other properties):
public class RootObject
{
public bool post_parameters_error_flag { get; set; }
public bool data_error_flag { get; set; }
public int row_count { get; set; }
public string message { get; set; }
public List<string> title { get; set; }
public List<string> data { get; set; }
}
var result = await HTTPRequest.PostAsyncResponse(URL, Params)
var item = JsonConvert.DeserializeObject<RootObject>(result);
var data = item.data;
Try this,
var data = JObject.Parse(await HTTPRequest.PostAsyncResponse(URL, Params))["data"]
OR
var jsonObject = (JObject)JsonConvert.DeserializeObject(await HTTPRequest.PostAsyncResponse(URL, Params));
var data = (JObject)(jsonObject.Property("data").Value);

Cartesian Product of Anonymous type

I am working on code which will give Cartesian product of two anonymous types. These 2 anonymous types are generated from database.
Code for 1st anonymous type:
private IEnumerable<object> GetItem()
{
return _unitOfWork.GetRepository<Item>()
.ListAll()
.Select(x => new
{
itemId = x.Id,
itemName = x.Name
})
}
Code for 2nd anonymous type:
private IEnumerable<object> GetVenue()
{
return _unitOfWork.GetRepository<Venue>()
.ListAll()
.Select(x => new
{
locationName = x.Address.City,
venueId = x.VenueId,
venueName = x.Name
})
}
I have following method to get the data and perform Cartesian product and return the data.
public object GetRestrictLookupInfo(IEnumerable<int> lookupCombinations)
{
IEnumerable<object> restrictList = new List<object>();
if (lookupCombinations.Contains(1))
{
var tempProductProfileList = GetItem();
restrictList = tempProductProfileList.AsEnumerable();
}
if (lookupCombinations.Contains(2))
{
var tempProductGroupList = GetVenue();
restrictList = (from a in restrictList.AsEnumerable()
from b in tempProductGroupList.AsEnumerable()
select new { a, b });
}
return restrictList;
}
I have controller which calls this method and return data in json format.
Controller Code
public HttpResponseMessage GetData(IEnumerable<int> lookupCombinations)
{
var lookupRestrictInfo = _sellerService.GetRestrictLookupInfo(lookupCombinations);
return Request.CreateResponse(HttpStatusCode.OK, lookupRestrictInfo);
}
Response expected is:-
[ {
"itemId": 1,
"itemName": "Music",
"locationName": "Paris",
"venueId": 99,
"venueName": "Royal Festival Hall"
} ]
Response which I receive is
[ {
"a": {
"itemId": 1,
"itemName": "Music"
},
"b": {
"locationName": "Paris",
"venueId": 99,
"venueName": "Royal Festival Hall" } }]
I am not able to get the expected JSON string.
You should start with the simplest possible code that shows your problem; your code above has a lot of complexities that may (or may not) have anything to do with your problem. Is this about manipulating anonymous types? Doing a Cartesian product with LINQ? Converting an object to JSON?
Here's one possible answer to what you might be looking for; notice that you can pass around anonymous types using generics instead of object.
namespace AnonymousTypes
{
class Program
{
static string Serialize(object o)
{
var d = (dynamic)o;
return d.ItemId.ToString() + d.ItemName + d.VenueId.ToString() + d.LocationName + d.VenueName;
}
static string GetData<T>(IEnumerable<T> result)
{
var retval = new StringBuilder();
foreach (var r in result)
retval.Append(Serialize(r));
return retval.ToString();
}
static string GetRestrictLookupInfo()
{
var restrictList = new[] { new { Id = 1, Name = "Music" }, new { Id = 2, Name = "TV" } };
var tempProductGroupList = new[] { new { LocationName = "Paris", Id = 99, Name = "Royal Festival Hall" } };
var result = from item in restrictList
from venue in tempProductGroupList
select new
{
ItemId = item.Id,
ItemName = item.Name,
LocationName = venue.LocationName,
VenueId = venue.Id,
VenueName = venue.Name
};
return GetData(result);
}
public static string GetData()
{
return GetRestrictLookupInfo();
}
static void Main(string[] args)
{
var result = GetData();
}
}
}
If that's not what you're looking for, you might start with code that doesn't use anonymous types, such as
namespace AnonymousTypes
{
sealed class Item
{
public int Id { get; set; }
public string Name { get; set; }
}
sealed class Venue
{
public string LocationName { get; set; }
public int Id { get; set; }
public string Name { get; set; }
}
sealed class ItemAndVenue
{
public int ItemId { get; set; }
public string ItemName { get; set; }
public string LocationName { get; set; }
public int VenueId { get; set; }
public string VenueName { get; set; }
}
class Program
{
static IEnumerable<Item> GetItem()
{
return new[] { new Item { Id = 1, Name = "Music" } };
}
static IEnumerable<Venue> GetVenue()
{
return new[] { new Venue { LocationName = "Paris", Id = 99, Name = "Royal Festival Hall" } };
}
static IEnumerable<ItemAndVenue> GetRestrictLookupInfo()
{
var restrictList = GetItem();
var tempProductGroupList = GetVenue();
var result = from item in restrictList
from venue in tempProductGroupList
select new ItemAndVenue
{
ItemId = item.Id,
ItemName = item.Name,
LocationName = venue.LocationName,
VenueId = venue.Id,
VenueName = venue.Name
};
return result;
}
static string GetData()
{
var v = GetRestrictLookupInfo().First();
return v.ItemId.ToString() + v.ItemName + v.VenueId.ToString() + v.LocationName + v.VenueName;
}
static void Main(string[] args)
{
var result = GetData();
}
}
}
In order to produce a single item in the output you need to create a new type, named or anonymous. Since you are using objects rather than actual types, the quickest approach is to cast them to dynamic:
var tempProductGroupList = GetVenue();
restrictList = (from a in restrictList.Cast<dynamic>()
from b in tempProductGroupList.Cast<dynamic>()
select new {
itemId = (int)a.itemId,
itemName = (string)a.itemName,
locationName = (string)b.locationName,
venueId = (int)b.venueId,
venueName = (string)b.venueName
});
This code is tightly coupled to the code producing both lists, because it assumes the knowledge of the field names of types passed into it dynamically. Any change in the structure of source data must be followed by a change in the code making combinations. In addition, it defeats run-time checking, so you need to be very careful with this code.
Try to create a simple object instead of nesting:
select new { a.itemId, a.itemName, b.locationName }
Like an option:
public object GetRestrictLookupInfo(IEnumerable<int> lookupCombinations)
{
List<Dictionary<string, object>> result = new List<Dictionary<string, object>>();
if (lookupCombinations.Contains(1))
{
var tmp = _unitOfWork.GetRepository<Item>()
.ListAll()
.Select(x => new
{
itemId = x.Id,
itemName = x.Name
})
.Select(x =>
{
var dic = new Dictionary<string, object>();
dic.Add(nameof(x.itemId), x.itemId);
dic.Add(nameof(x.itemName), x.itemName);
return dic;
});
result.AddRange(tmp);
}
if (lookupCombinations.Contains(2))
{
var tmp = _unitOfWork.GetRepository<Venue>()
.ListAll()
.Select(x => new
{
locationName = x.Address.City,
venueId = x.VenueId,
venueName = x.Name
})
.Select(x =>
{
var dic = new Dictionary<string, object>();
dic.Add(nameof(x.locationName), x.locationName);
dic.Add(nameof(x.venueId), x.venueId);
dic.Add(nameof(x.venueName), x.venueName);
return dic;
});
result = result.SelectMany(r => tmp.Select(t => r.Concat(t)));
}
return result;
}
It looks like some magic. I uses dictionary instead of object. It can be make in more clear way (extract few methods), but the idea should be clear.
Then, during serialization it will be presented as you need.

how to create a json format using json.net in c#

I need a final json format as follows and that should be dynamic.
{
"product_items" :
[
{
"_at" : 1,
"product_id" : "999"
},
{
"_at" : 2,
"quantity" : 2.00
},
{
"_delete_at" : 3
}
]
}
How to create a json format as above in the code._at field is dynamic.sometimes it might be 2 and sometimes it might be 10.I dont have idea on to generate the json dynamically in c#.
class Test
{
public ProductItem[] product_items { get; set; }
class ProductItem
{
public int[] _at { get; set; }
public int[] _delete { get; set; }
public int[] quantity { get; set; }
public string[] product_id{get;set;}
}
}
i have create the the properties for json as above.
I'm using Newtonsoft library
Your class should look more like this:
public class ProductItem
{
public int _at { get; set; }
public string product_id { get; set; }
public double? quantity { get; set; }
public int? _delete_at { get; set; }
}
public class ProductItemObject
{
public List<ProductItem> product_items { get; set; }
}
A example on serializing :
List<ProductItem> list = new List<ProductItem>();
ProductItemObject o = new ProductItemObject { product_items = list };
var item1 = new ProductItem { _at = 1, product_id = "001" };
var item2 = new ProductItem { _at = 2, quantity = 2.00 };
var item3 = new ProductItem { _delete_at = 3 };
list.Add(item1);
list.Add(item2);
list.Add(item3);
string json = JsonConvert.SerializeObject(o, Formatting.Indented);
// json string :
// {
// "product_items": [
// {
// "_at": 1,
// "product_id": "001",
// "quantity": null,
// "_delete_at": null
// },
// {
// "_at": 2,
// "product_id": null,
// "quantity": 2.0,
// "_delete_at": null
// },
// {
// "_at": 0,
// "product_id": null,
// "quantity": null,
// "_delete_at": 3
// }
// ]
//}
An alternative full dynamic that gets u the same Json string without any model :
var jsonObject = new JObject();
dynamic objectList = jsonObject;
objectList.product_items = new JArray() as dynamic;
dynamic item = new JObject();
item._at = 1;
item.product_id = "999";
objectList.product_items.Add(item);
item = new JObject();
item._at = 2;
item.quantity = 2.00;
objectList.product_items.Add(item);
item = new JObject();
item._delete_at = 3;
objectList.product_items.Add(item);
string json = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObject, Formatting.Indented);
Well, if I understand you properly and you just need to be able to generate that json, the product list should be dynamic with maybe anonymous classes then:
public class Products
{
public Products()
{
product_items = new List<dynamic>();
}
public List<dynamic> product_items { get; set; }
}
products.product_items.Add(new { _at = 1, product_id = "999" });

jQuery REST POST JSON List<Object>

I'm having the following classes on C#:
public class Record
{
public Record()
{
this.Artists = new List<Artist>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<Artist> Artists { get; set; }
}
public class Artist
{
public Artist()
{
this.Songs = new List<Song>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Album { get; set; }
public List<Song> Songs { get; set; }
}
public class Song
{
public Song()
{
}
public int Id { get; set; }
public string Name { get; set; }
}
Then we add some data:
Record record = new Record();
record.Id = 1;
record.Name = "Some music";
record.Description = "Something...";
Artist artist = new Artist();
artist.Id = 1;
artist.Name = "Bob Marley";
artist.Album = "Legend";
Song song = new Song();
song.Id = 1;
song.Name = "No woman no cry";
artist.Songs.Add(song);
song = new Song();
song.Id = 2;
song.Name = "Could you be loved";
artist.Songs.Add(song);
record.Artists.Add(artist);
artist = new Artist();
artist.Id = 2;
artist.Name = "Major Lazer";
artist.Album = "Free the universe";
song = new Song();
song.Id = 2;
song.Name = "Get free";
artist.Songs.Add(song);
song = new Song();
song.Id = 2;
song.Name = "Watch out for this";
artist.Songs.Add(song);
record.Artists.Add(artist);
string jsonVal = JsonConvert.SerializeObject(record);
textBox1.Text = jsonVal;
The last 2 lines will serialize the record type object to JSON using Newtonsoft Json and here is the resulted JSON:
{"Id":1,"Name":"Some music","Description":"Something...","Artists":[{"Id":1,"Name":"Bob Marley","Album":"Legend","Songs":[{"Id":1,"Name":"No woman no cry"},{"Id":2,"Name":"Could you be loved"}]},{"Id":2,"Name":"Major Lazer","Album":"Free the universe","Songs":[{"Id":2,"Name":"Get free"},{"Id":2,"Name":"Watch out for this"}]}]}
Now I need to create this JSON using javascript and POST that json to WEB API endpoint. What I don't know is how to create the object in javascript.
I know there is JSON.stringify(object) that will serialize the object, but how can I create the List ???
I know I can do something like this:
var record =
{
Name: "Whatever",
Description: "Something else",
//How can I make the List<object>
};
I'm thinking about array and probably this is the right one ... something like this:
var record =
{
Name: "Whatever",
Description: "Something else",
Artists:
{
"Name": "Artist Name",
"Album": "Some Album".
"Songs":
{
"Name": "SongName"
}
},
};
and last:
JSON.stringify(record);
You should use a JavaScript Array for a .NET collection.
var record = {
name: "Whatever",
description: "Something else",
artists: [{
name: "Artist Name",
album: "Some Album",
songs: [{
name: "Some Song"
}]
}]
};
Web API will treat the JSON as case insensitive.
You need to use this code for jQuery REST POST JSON List
var jsonObj = [];
$.each({ name: "John", lang: "JS" }, function (key,value) {
jsonObj.push(
{
key: value
});
});

Json.NET serialize property on the same level

I have a very long and complex JSON to send to an external web service.
The JSON has all the properties at the same level:
public class Request
{
[JsonProperty(PropertyName = "prop1a")]
public string Prop1A;
[JsonProperty(PropertyName = "prop2a")]
public string Prop2A;
[JsonProperty(PropertyName = "prop3a")]
public string Prop3A;
[JsonProperty(PropertyName = "prop1b")]
public string Prop1B;
[JsonProperty(PropertyName = "prop2b")]
public string Prop2B;
[JsonProperty(PropertyName = "prop3b")]
public string Prop3B;
// [...]
}
The resulting JSON:
// valid JSON
{ prop1a: "", prop2a: "", prop3a: "", prop1b: "", prop2b: "", prop3b: "" }
In order to work better I have logically separated similar properties into smaller classes:
public class Request
{
public AggregatedPropsA MyAggregatedPropsA;
public AggregatedPropsB MyAggregatedPropsB;
}
public class AggregatedPropsA
{
[JsonProperty(PropertyName = "prop1a")]
public string Prop1A;
[JsonProperty(PropertyName = "prop2a")]
public string Prop2A;
[JsonProperty(PropertyName = "prop3a")]
public string Prop3A;
}
The problem is that the json string is now invalid string because the properties are serialized on different levels:
// invalid JSON
{ MyAggregatedPropsA: { prop1a: "", prop2a: "", prop3a: ""}, MyAggregatedPropsB: { prop1b: "", prop2b: "", prop3b: "" } }
Is it possible to get a JSON like the first, using the second class structure?
var obj = new { x = new { a = 1, b = 2 }, y = new { c = 3, d = 4 } };
Func<JToken, IEnumerable<JProperty>> flatten = null;
flatten = token => token.Concat(token.SelectMany(t => t.Children().SelectMany(y => flatten(y))))
.OfType<JProperty>()
.Where(p => p.Value is JValue || p.Value is JArray);
var dict = flatten(JToken.FromObject(obj))
.ToDictionary(p => p.Name, p => p.Value);
var json = JsonConvert.SerializeObject(dict);

Categories

Resources