The fields are getting ignored. I'm successfully getting back a list of 2 objects, but none of the fields are populated. What am I doing wrong? (Unfortunately I don't have control over the json format. It arrives in exactly this structure.
using System.Web.Script.Serialization;
public void myMethod {
string myContent = #"
[
{
"my_object": {
"city": "city 1",
"myAge": 15
}
},
{
"my_object": {
"city": "city 2",
"myAge": 18
}
}
]";
JavaScriptSerializer serializer = new JavaScriptSerializer();
List<my_object> list = serializer.Deserialize<List<my_object>>(myContent);
}
public class json_content {
public string city { get; set; }
public int myAge { get; set; }
}
This code solves your problem:
public void myMethod()
{
string myContent = #"
[
{
""json_content"": {
""city"": ""city 1"",
""myAge"": 15
}
},
{
""json_content"": {
""city"": ""city 2"",
""myAge"": 18
}
}
]";
JavaScriptSerializer serializer = new JavaScriptSerializer();
List<wrapper> list = serializer.Deserialize<List<wrapper>>(myContent);
}
public class wrapper
{
public json_content json_content { get; set; }
}
public class json_content
{
public string city { get; set; }
public int myAge { get; set; }
}
You have list of objects with one property json_content in your JSON, but expect list directly containing json_content objects.
Most likely fix is to remove intermediate object from JSON (if you control it):
[
{
"city": "city 1",
"myAge": 15
},...
];
If you don't control JSON add outer class:
class JsonOuterContent
{
public JsonContent json_content;
}
List<JsonOuterContent> list = serializer
.Deserialize<List<JsonOuterContent>>(myContent);
Related
I have below json which I need to deserialize in C# -
{
"clientSettings":[
{
"clientId":12345,
"entries":[
{
"key":"abc",
"value":false
},
{
"key":"def",
"value":false
},
{
"key":"ghi",
"value":false
}
]
},
{
"clientId":9876,
"entries":[
{
"key":"lkmn",
"value":false
}
]
}
],
"productSettings":[
{
"productId":11,
"entries":[
{
"key":"jkl",
"value":true
},
{
"key":"mno",
"value":true
}
]
},
{
"productId":12,
"entries":[
{
"key":"jkl",
"value":true
},
{
"key":"mno",
"value":true
}
]
}
],
"customerSettings":[
{
"key":"enableData",
"value":false
},
{
"key":"minPriceValue",
"value":"10.28"
},
{
"key":"presentData",
"value":"AEGIS"
}
],
"thothTest":{
"9876":[
"K"
],
"5431":[
"A",
"L"
],
"5123":[
"L"
]
},
"osirisTest":{
"7678":[
"K"
]
}
}
Below is the classes I created to deserialzie json into -
public class ProcessHolder : Holder
{
public IDictionary<int, ISet<string>> OsirisTest { get; set; }
public IDictionary<int, ISet<string>> ThothTest { get; set; }
}
public class Holder
{
public IList<Mapping> CustomerSettings { get; set; }
public IList<ClientSettingsMapping> ClientSettings { get; set; }
public IList<ProductSettingsMapping> ProductSettings { get; set; }
}
public class Mapping
{
public string Key { get; set; }
public object Value { get; set; }
}
public class ProductSettingsMapping : Mapping
{
public int ProductId { get; set; }
}
public class ClientSettingsMapping : Mapping
{
public int ClientId { get; set; }
}
I want to load all customerSettings values into CustomerSettings object of Holder class.
Similarly I want to load all clientSettings values into ClientSettings object of Holder class.
Similarly all productSettings values into ProductSettings object of Holder class.
Similarly thothTest values into ThothTest and osirisTest values into OsirisTest object.
I was trying with below code but somehow I am not able to see Key and Value variables being populated inside Mapping class object after deserializing my above json.
private static readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
public static void Main(string[] args)
{
var jsonContent = File.ReadAllText("/beta/Downloads/test.json");
var config = JsonConvert.DeserializeObject<ProcessHolder>(jsonContent, serializerSettings);
if (config == null)
{
Console.WriteLine("Some Parsing Issue");
}
// using config object here
}
What is wrong I am doing here? I just need to deserialize my json into above classes and give me ProcessHolder object back which I can use later on.
Looking at your JSON, clientSettings and productSettings have entries array. There is no corresponding matching property in your class definition for same.
I would suggest to modify your class definition as per JSON. Try below and see if it helps:
public class ProductSettingsMapping
{
public int ProductId { get; set; }
public IList<Mapping> Entries { get; set; }
}
public class ClientSettingsMapping
{
public int ClientId { get; set; }
public IList<Mapping> Entries { get; set; }
}
Second option - if you are not able to modify classes, you can amend JSON. I am providing sample for clientSettings
{
"clientSettings": [
{
"clientId": 12345,
"key": "abc",
"value": false
},
{
"clientId": 12345,
"key": "def",
"value": false
},
{
"clientId": 12345,
"key": "ghi",
"value": false
},
{
"clientId": 9876,
"key": "lkmn",
"value": false
}
]
}
You can update productSettings accordingly.
Third option is to parse into JObject and then convert to your classes.
A sample for clientSettings
static void Main(string[] args)
{
var json = "{'clientSettings':[{'clientId':12345,'entries':[{'key':'abc','value':false},{'key':'def','value':false},{'key':'ghi','value':false}]},{'clientId':9876,'entries':[{'key':'lkmn','value':false}]}],'productSettings':[{'productId':11,'entries':[{'key':'jkl','value':true},{'key':'mno','value':true}]},{'productId':12,'entries':[{'key':'jkl','value':true},{'key':'mno','value':true}]}],'customerSettings':[{'key':'enableData','value':false},{'key':'minPriceValue','value':'10.28'},{'key':'presentData','value':'AEGIS'}],'thothTest':{'9876':['K'],'5431':['A','L'],'5123':['L']},'osirisTest':{'7678':['K']}}";
var parsed = JObject.Parse(json);
var parsedClientSettings = parsed["clientSettings"];
List<ClientSettingsMapping> clientSettings = new List<ClientSettingsMapping>();
foreach (var parsedClientSetting in parsedClientSettings)
{
var clientId = parsedClientSetting.Value<int>("clientId");
foreach (var entry in parsedClientSetting["entries"])
{
clientSettings.Add(new ClientSettingsMapping { ClientId = clientId, Key = entry["key"].ToString(), Value = entry["value"].ToString() });
}
}
ProcessHolder processHolder = new ProcessHolder() { ClientSettings = clientSettings };
Console.ReadLine();
}
You should define "entries" in both ProductSettingsMapping and ClientSettingsMapping class.
public class ProductSettingsMapping
{
public int ProductId { get; set; }
public IList<Mapping> entries { get; set; }
}
public class ClientSettingsMapping
{
public int ClientId { get; set; }
public IList<Mapping> entries { get; set; }
}
I was working with a .net core 3.1 Web API. Which is getting data from an external API. Following is my code Controller part
[HttpGet("transinfo/{id}")]
public Object GettransactionData(int id)
{
var result=_transaction.GettransactionDetails(id).Result;
List<PipeLineResponse> P = JsonConvert.DeserializeObject<List<PipeLineResponse>>(result.ToString());
PipeLineResponseObject P1 = new PipeLineResponseObject();
P1.data = P;
return P1;
}
And my service code as follows
public async Task<Object> GettransactionDetails(int id)
{
string request=//fetched from db
var stringContent = new StringContent(request);
Client = utilities.GetHttpClient();
string apiEndpoint=//External API URL
HttpResponseMessage httpResponseMessage = await Client.PostAsync(apiEndpoint, stringContent);
if (httpResponseMessage.IsSuccessStatusCode)
{
return await httpResponseMessage.Content.ReadAsAsync<Object>();
}
}
But i am getting the result in following format (response from postman)
{
"data": [
{
"Tranid": "34540d40-7db8-44c1-9a2a-5072c2d01756",
"fields": {
"Fields.10": "1001",
"Fields.11": "Test1",
"Fields.12": "Fixed1"
}
},
{
"Tranid": "145800f9-c4a5-4625-84d7-29af5e674a14",
"fields": {
"Fields.10": "1002",
"Fields.11": "Test2",
"Fields.12": "Fixed2"
}
}
]
}
But i need the data in following format
{
"data": [
{
"TransactionID": "34540d40-7db8-44c1-9a2a-5072c2d01756",
"fieldsList": [
{
"fieldId": "10",
"fieldValue": "1001"
},
{
"fieldId": "11",
"fieldValue": "Test1"
},
{
"fieldId": "12",
"fieldValue": "Fixed1"
}
]
},
{
"TransactionID": "145800f9-c4a5-4625-84d7-29af5e674a14",
"fieldsList": [
{
"fieldId": "10",
"fieldValue": "1002"
},
{
"fieldId": "11",
"fieldValue": "Test2"
},
{
"fieldId": "12",
"fieldValue": "Fixed2"
}
]
}
]
}
How can i achieve this ? is possible to deserialise using JObject or JArray? Please help.
i have tried to create following model class and tried to deserialise but not getting result as expected.
public class PipeLineResponse
{
public string TransactionID { get; set; }
public List<Dictionary<string, string>> fields { get; set; }
}
public class PipeLineResponseObject
{
public List<PipeLineResponse> data { get; set; }
}
How to create that json in that format any DTO or Automapper will work ? Please help me with samples.
The solution that I am laying down here takes the DTO approach. The response from the service is being deserialized to the DTO, which further is being manually mapped to the final ViewModel that we are sending to the client. By no means, this implementation is production-ready and there is scope for improvement, for which I am adding in comments. But this gives a detailed understanding of how we can handle these kind of scenarios. We are making use of Newtonsoft.Json, which can be pulled into your project via the NuGet package manager.
Structure of the DTO
// RootDTO.cs
// This structure is directly based on the response obtained from remote service.
public class Fields
{
[JsonProperty(PropertyName ="Fields.10")]
public string Fields10 { get; set; }
[JsonProperty(PropertyName = "Fields.11")]
public string Fields11 { get; set; }
[JsonProperty(PropertyName = "Fields.12")]
public string Fields12 { get; set; }
}
public class Datum
{
public string Tranid { get; set; }
public Fields fields { get; set; }
}
public class RootDTO
{
[JsonProperty(PropertyName ="data")]
public List<Datum> data { get; set; }
}
Structure of ViewModel
// PipelineResponse.cs
public class FieldsList
{
public string fieldId { get; set; }
public string fieldValue { get; set; }
}
public class ResponseDatum
{
[JsonProperty(PropertyName = "TransactionID")]
public string TransactionID { get; set; }
public List<FieldsList> fieldsList { get; set; }
}
public class PipelineResponse
{
public List<ResponseDatum> data { get; set; }
}
Deserializing the response to the DTO
// ...other code
var responseString = await httpResponseMessage.Content.ReadAsAsync<Object>();
// This is where the DTO object is created. This should be mapped to view model type.
var responseDTO = JsonConvert.DeserializeObject<RootDTO>(responseString);
Mapping the DTO to ViewModel
The mapping from DTO type to ViewModel type needs to be done before sending the response to the client. It is the view model type that is sent to the client. This logic can be placed within a separate helper (ideally, to separate concerns) or any other location as per the practices you are following.
public PipelineResponse ConvertResponseDTOToResponse(RootDTO responseDTO)
{
// FieldId is being hardcoded here. Instead, you can use Reflection to
// fetch the property name, split on '.' and take the item at index 1.
// Notice that DTO properties have "JsonProperty" attributes for this.
try
{
List<ResponseDatum> responseList = new List<ResponseDatum>();
if (responseDTO != null)
{
// Reflection can be used to avoid hardcoding on 'fieldId'
foreach (var item in responseDTO.data)
{
var responseDataObj = new ResponseDatum
{
TransactionID = item.Tranid,
fieldsList = new List<FieldsList>
{
new FieldsList
{
fieldValue = item.fields.Fields10,
fieldId = "10"
},
new FieldsList
{
fieldValue = item.fields.Fields11,
fieldId = "11"
},
new FieldsList
{
fieldValue = item.fields.Fields12,
fieldId = "12"
}
}
};
responseList.Add(responseDataObj);
}
}
// This object is what you return from your controller endpoint finally.
// The serialized response of this object is of the json structure you need
return new PipelineResponse { data = responseList };
}
catch (Exception ex)
{
throw ex;
}
}
I would like to deserialize a json to object. The json is like below. But one property value maybe string or array, does anyone know how to handle this?
{
"name": "123", //Name
"properties": [
{
"propertyId": "Subject", // property id
"value": [
{
"entityId": "math", //entity id
"entityTypeId": "MATH" //entity type id
}
]
},
{
"propertyId": "Description",
"value": "Hello World."
}
]
}
The class is like below.
//The object
public class Content
{
public Content()
{
//Properties is List.
Properties = new List<Property>();
}
[JsonProperty(PropertyName = "name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "properties")]
public List<Property> Properties { get; set; }
}
public class Property
{
public Property()
{
Value = new List<Value>();
}
[JsonProperty(PropertyName = "propertyId")]
public string PropertyDefId { get; set; }
//Actually this property value can also be string, that's the problem.
[JsonProperty(PropertyName = "value")]
public List<Value> Value { get; set; }
}
//Value object
public class Value
{
//Have to write comments.
[JsonProperty(PropertyName = "entityId")]
public string EntityId { get; set; }
//Have to write comments.
[JsonProperty(PropertyName = "entityTypeId")]
public string EntityTypeId { get; set; }
}
I've done this in Java with Gson liblary and it was like
JsonObject field = parser.parse(json).getElementAsJSONObject();
if (field.isPrimitive()) {
String text = field.asString();
} else if (field.isArray()) {
JSONArray array = field.asArray();
}
I wrote this code from my memory so not 100% reliable. I don't know any solution for C# though.
$.parseJSON will convert your string to the correct object even if the property type is different for two different properties.
http://jsfiddle.net/mdanielc/e0acsyp1/2/
var jsonString = '{"name": "123","properties": [{"propertyId": "Subject","value": [{"entityId":"math","entityTypeId": "MATH" }]},{"propertyId": "Description","value": "Hello World."}]}';
var jsonobj = $.parseJSON(jsonString);
alert(jsonobj.properties[0].value[0].entityId);
alert(jsonobj.properties[1].value);
});
I have a two simple PHP class
class Order{
public $orderNo;
public $lines = array();
public $paid = false;
public function addLine(OrderLine $line) {
$this->lines[] = $line;
}
public function setPaid($paid = true) {
$this->paid = true;
}
}
class OrderLine{
public function __construct($item, $amount){
$this->item = $item;
$this->amount = $amount;
}
public $item;
public $amount;
public $options;
}
Serialize object uses https://github.com/mindplay-dk/jsonfreeze
...
$json = new JsonSerializer;
$data = $json->serialize($order);
Have output:
{
"#type": "Order",
"orderNo": 123,
"lines": [{
"#type": "OrderLine",
"item": "milk \"fuzz\"",
"amount": 3,
"options": null
},{
"#type": "OrderLine",
"item": "cookies",
"amount": 7,
"options": {
"#type": "#hash",
"flavor": "chocolate",
"weight": "1\/2 lb"
}
}],
"paid": true
}
Send the string XMLRPC in VB.NET
As using Newtonsoft JSON get a live object?
As well as how to create a compatible format by analogy with the json string of living VB.net OR C# object?
Here's something you could start with. You create some classes with properties which represent the JSON Format (untested code, just as idea):
public class MyData
{
[JsonProperty("#type")]
public string Type { get; set; }
[JsonProperty("#orderNo")]
public int OrderNo { get; set;
[JsonProperty("paid")]
public bool Paid { get; set; }
[JsonProperty("lines")]
public List<MyDataLine> Lines { get; set; }
}
public class MyDataLines
{
[JsonProperty("#type")]
public string Type { get; set; }
[JsonProperty("options")]
public MyDataLinesOptions Options { get; set; }
// ... more
}
public class MyDataLinesOptions
{
// ... more
}
Then you can serialize and deserialize the the data like this:
string json = "the json data you received";
MyData myData = JsonConvert.DeserializeObject<MyData>(json);
// ...
json = JsonConvert.SerializeObject(myData);
"#type": "Order"
and
"#type": "OrderLine",
this is not a property, this is an indication of the type of the object
Given:
The classes:
public class Venue
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("location")]
public Location Location { get; set; }
}
public class Location
{
public long Lat { get; set; }
public long Lng { get; set; }
public int Distance { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
public class Response
{
private List<Venue> _venues;
[JsonProperty("venues")]
public List<Venue> Venues
{
get { return _venues ?? (_venues = new List<Venue>()); }
set { _venues = value; }
}
}
And a response request:
{
"meta":{
"code":200
},
"response":{
"venues":[
{
"id":"4f96a5aee4b01cb74e4dc3c6",
"name":"Centro",
"contact":{
},
"location":{
"address":"Centro",
"lat":-21.256906640441052,
"lng":-48.31978432813259,
"distance":185,
"city":"Jaboticabal",
"state":"SP",
"country":"Brazil",
"cc":"BR"
},
"canonicalUrl":"https:\/\/foursquare.com\/v\/centro\/4f96a5aee4b01cb74e4dc3c6",
"categories":[
{
"id":"4f2a25ac4b909258e854f55f",
"name":"Neighborhood",
"pluralName":"Neighborhoods",
"shortName":"Neighborhood",
"icon":{
"prefix":"https:\/\/foursquare.com\/img\/categories_v2\/parks_outdoors\/neighborhood_",
"suffix":".png"
},
"primary":true
}
],
"verified":false,
"restricted":true,
"stats":{
"checkinsCount":1106,
"usersCount":86,
"tipCount":0
},
"specials":{
"count":0,
"items":[
]
},
"hereNow":{
"count":0,
"groups":[
]
},
"referralId":"v-1376511204"
},
{
"id":"4c38b0b21a38ef3b56b39221",
"name":"Ice by Nice",
"contact":{
},
"location":{
"address":"Jaboticabal Shopping",
"lat":-21.25513775,
"lng":-48.32320093,
"distance":253,
"city":"Jaboticabal",
"state":"SP",
"country":"Brazil",
"cc":"BR"
},
"canonicalUrl":"https:\/\/foursquare.com\/v\/ice-by-nice\/4c38b0b21a38ef3b56b39221",
"categories":[
{
"id":"4bf58dd8d48988d1c9941735",
"name":"Ice Cream Shop",
"pluralName":"Ice Cream Shops",
"shortName":"Ice Cream",
"icon":{
"prefix":"https:\/\/foursquare.com\/img\/categories_v2\/food\/icecream_",
"suffix":".png"
},
"primary":true
}
],
"verified":false,
"restricted":true,
"stats":{
"checkinsCount":656,
"usersCount":309,
"tipCount":15
},
"specials":{
"count":0,
"items":[
]
},
"hereNow":{
"count":2,
"groups":[
{
"type":"others",
"name":"Other people here",
"count":2,
"items":[
]
}
]
},
"referralId":"v-1376511204"
}
]
}
}
When using JSON.NET like so:
Response response = JsonConvert.DeserializeObject<Response>(jsonString);
The deserialized response object has a empty list of venues, What am I doing wrong?
Thanks
There's a bit of a mismatch in what you're trying to deserialize and the class you have defined to deserialize into. You unfortunately need yet another layer of indirection. Note the response has;
// theres an outer object here which contains response
{
"meta":{ "code":200 },
"response":{
// you're trying to deserialize this, but it's not the entire response, it's a property of an anonymous object
}
}
So if I make a new class;
public class ResponseWrapper
{
public object meta;
public Response response;
}
And instead do;
ResponseWrapper response = JsonConvert.DeserializeObject<ResponseWrapper>(jsonString);
Then it will work.
Note that when you're deserializing using json.NET you have to define a structure that exactly matches the json. In this case you're leaving out the outer most object. It is kind of an annoyance and leads to a lot of code like what I just wrote but that's just the way it goes sometimes.