This sound very simple. But I can't find how to do it.
I've receiving a bad json from an api. the actual json is inside a string
Instead of
[{\"ProductId\":1,\"ProductName\":\"abuka\",\"Rate\":6.00,\"Quantity\":10.000},{\"ProductId\":2,\"ProductName\":\"abuka\",\"Rate\":6.00,\"Quantity\":10.000},{\"ProductId\":3,\"ProductName\":\"abuka\",\"Rate\":6.00,\"Quantity\":10.000}]
I'm receiving
"[{\"ProductId\":1,\"ProductName\":\"abuka\",\"Rate\":6.00,\"Quantity\":10.000},{\"ProductId\":2,\"ProductName\":\"abuka\",\"Rate\":6.00,\"Quantity\":10.000},{\"ProductId\":3,\"ProductName\":\"abuka\",\"Rate\":6.00,\"Quantity\":10.000}]"
When I try
JsonConvert.DeserializeObject<List<Product>> (jsonString)
I get error Error converting to System.Collections.Generic.List
How can I extract it into a valid JSON string before deserialising?
If you've got a value which is "a string serialized as JSON", then just deserialize that first. Assuming your string genuinely starts and ends with a double quote, you should be fine to call JsonConvert.DeserializeObject<string> to do that unwrapping:
using System;
using System.IO;
using Newtonsoft.Json;
public class Model
{
public string Foo { get; set; }
}
public class Test
{
static void Main()
{
string json = "\"{\\\"foo\\\": \\\"bar\\\"}\"";
Console.WriteLine($"Original JSON: {json}");
string unwrappedJson = JsonConvert.DeserializeObject<string>(json);
Console.WriteLine($"Unwrapped JSON: {unwrappedJson}");
Model model = JsonConvert.DeserializeObject<Model>(unwrappedJson);
Console.WriteLine($"model.Foo: {model.Foo}");
}
}
Thanks Jon Skeet. Referring to your answer, the users who are not using "Newtonsoft.Json" in the application but the Web API which gives the data uses "Newtonsoft.Json" for them below one might be helpful.
Example :
In WEB API - "Newtonsoft.Json" used
The application(might be MVC/ASP.NET WebForms) which consumes WEB API, doesn't use "Newtonsoft.Json". So, they can reference to "System.Web.Extensions" and use using System.Web.Script.Serialization to desialize the json data.
using System.Collections.Generic;
using System.Web.Script.Serialization;
namespace DesrializeJson1ConsoleApp
{
class Program
{
static void Main(string[] args)
{
string jsonstring = "\"[{\\\"ProductId\\\":1,\\\"ProductName\\\":\\\"abuka\\\",\\\"Rate\\\":6.00,\\\"Quantity\\\":10.000},{\\\"ProductId\\\":2,\\\"ProductName\\\":\\\"abuka\\\",\\\"Rate\\\":6.00,\\\"Quantity\\\":10.000},{\\\"ProductId\\\":3,\\\"ProductName\\\":\\\"abuka\\\",\\\"Rate\\\":6.00,\\\"Quantity\\\":10.000}]\"";
var serializer = new JavaScriptSerializer();
var jsonObject = serializer.Deserialize<string>(jsonstring);
List<Product> lstProducts = serializer.Deserialize<List<Product>>(jsonObject);
foreach(var item in lstProducts)
{
Console.WriteLine("ProductId :" + item.ProductId);
Console.WriteLine("ProductName :" + item.ProductName);
Console.WriteLine("Rate :" + item.Rate);
Console.WriteLine("Quantity :" + item.Quantity);
Console.WriteLine("--------------------------");
}
Console.Read();
}
}
public class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public double Rate { get; set; }
public double Quantity { get; set; }
}
}
OUTPUT
Related
I have JSON and I need to deserialize it.Json file includes XML inside. Any suggestions?
{"nt":0,"r":true,"o":[{"test":"20fgfgdfgdfAZ20AIgdg151","fddf":"ZregrIPgdffgfSgfg","d":"<DataPDU xmlns="urn:cma:stp:xsd:stp.1.0">
<Body>
</AppHdr>
<Document xmlns="urn:iso:">
.....
</Document></Body>
</DataPDU>"}]}
It appears as though your JSON string is invalid. You have quotation marks unescaped in the o[0].d, or the XML section. I have provided a version of the JSON with the escaped quotation marks below.
{
"nt": 0,
"r": true,
"o": [
{
"test": "20fgfgdfgdfAZ20AIgdg151",
"fddf": "ZregrIPgdffgfSgfg",
"d": "<DataPDU xmlns=\"urn:cma:stp:xsd:stp.1.0\"><Body></<Document xmlns=\"urn:iso:\"> ..... </Document></Body></DataPDU>"
}
]
}
Using .NET Core 3.1 and the System.Text.Json namespace you can deserialize the above json using something along the lines:
async Task Main()
{
string fileName = "ExampleJson.txt";
Example example = null;
using (FileStream fs = File.OpenRead(fileName))
{
example = await JsonSerializer.DeserializeAsync<Example>(fs);
}
}
Documentation on using the System.Text.Json namespace can be found here.
Note that " has to change to \" in your xml-STRING, understood that code won't work . ;)
using System.Text.Json;
public myJson()
{
string json = "<json>";
Rootobject jsonObject = JsonConvert.DeserializeObject<Rootobject>(json);
}
public class Rootobject
{
public int nt { get; set; }
public bool r { get; set; }
public O[] o { get; set; }
}
public class O
{
public string test { get; set; }
public string fddf { get; set; }
public string d { get; set; }
}
As part of my web api, I'm getting the following JSON returned.
["{\"InputType\":17,\"EngineSubType\":4,\"Filename\":\"targetFile.csv\",\"FileExtensionType\":\".csv\",\"IsLoadFile\":true,\"LoadContextId\":4121,\"ReportingDate\":\"2019-05-31T00:00:00\",\"IsSuccess\":false}"]
What I'm wanting to do is grab the value next to Filenameand assign it to my models Filename parameter.
In my project I've created a unit test to experiment with grabbing that value, but each attempt I've making is failing.
In my test I have following DTO Model:
public class HangfireTestDTO
{
public string InputType { get; set; }
public string Filename { get; set; }
}
Then my text logic is this:
[Fact]
public void TestDTO()
{
string data =
"[\"{\\\"InputType\\\":12,\\\"EngineSubType\\\":2,\\\"Filename\\\":\\\"targetFile.csv\\\",\\\"FileExtensionType\\\":\\\".csv\\\",\\\"IsLoadFile\\\":true,\\\"LoadContextId\\\":4120,\\\"ReportingDate\\\":\\\"2019-05-31T00:00:00\\\",\\\"IsSuccess\\\":false}\"]";
// fails here
var arguments = System.Text.Json.JsonSerializer.Deserialize<HangfireTestDTO>(data);
// This is wrong - ignore for now
Assert.Equal("targetFile.csv", arguments.ToString());
}
When I debug the above in my test it tells me the following:
The JSON value could not be converted to MyProject.HangfireTestDTO
My thinking then led me to try again by modifying the deserialize line to the following:
var arguments = System.Text.Json.JsonSerializer.Deserialize<IEnumerable<HangfireTestDTO>>(data).FirstOrDefault();
But when running it with the new line, I get the following error:
The JSON value could not be converted to System.Collections.Generic.List
What is it I'm doing wrong?
Your current JSON string is an array of strings. You need to first deserialize the JSON into a list of strings, then deserialize each of those strings as a DTO. Here's a complete example using your JSON:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
public class HangfireTestDTO
{
public int InputType { get; set; }
public int EngineSubType { get; set; }
public string Filename { get; set; }
public string FileExtensionType { get; set; }
}
class Program
{
static void Main()
{
string data =
"[\"{\\\"InputType\\\":12,\\\"EngineSubType\\\":2,\\\"Filename\\\":\\\"targetFile.csv\\\",\\\"FileExtensionType\\\":\\\".csv\\\",\\\"IsLoadFile\\\":true,\\\"LoadContextId\\\":4120,\\\"ReportingDate\\\":\\\"2019-05-31T00:00:00\\\",\\\"IsSuccess\\\":false}\"]";
// First deserialize the single string to a list of strings
List<string> jsonStrings = JsonSerializer.Deserialize<List<string>>(data);
// Then deserialize each of the strings to a DTO.
List<HangfireTestDTO> dtos = jsonStrings
.Select(json => JsonSerializer.Deserialize<HangfireTestDTO>(json))
.ToList();
Console.WriteLine(dtos.Count);
Console.WriteLine(dtos[0].Filename);
}
}
firstly your JSON is wrong
i would expect it too look more like
string data = #"[{""InputType"":12,""EngineSubType"":2,""Filename"":""targetFile.csv"",""FileExtensionType"":"".csv"",""IsLoadFile"":true,""LoadContextId"":4120,""ReportingDate"":""2019-05-31T00:00:00"",""IsSuccess"":false}]"
or
string data = "[{\"InputType\":17,\"EngineSubType\":4,\"Filename\":\"targetFile.csv\",\"FileExtensionType\":\".csv\",\"IsLoadFile\":true,\"LoadContextId\":4121,\"ReportingDate\":\"2019-05-31T00:00:00\",\"IsSuccess\":false}]"
second you have wrapped your JSON in [] this means a list of docs so Deserialize<HangfireTestDTO>(data); would be Deserialize<List<HangfireTestDTO>>(data); or some other IEnumerable
then you have serveral data mismatches 12 is a number not a string so InputType should be an int or double, IsSuccess is a bool, etc
finally you have lots of fields in your JSON that aren't on your object you need to explain to c# what to do with them either create the extra properties or provide a KeyValue store it can put them in
ie
[JsonExtensionData]
public Dictionary<string, object> ExtensionData { get; set; }
EDIT following the comment you made if that is really how the data is coming out your DB then its an array of strings where the strings are JSON encoded
in which case you will need to read the strings then parse them after
var jsonlist = JsonSerializer.Deserialize<List<string>>(data);
foreach(string json in jsonlist )
var dto = JsonSerializer.Deserialize<HangfireTestDTO>(json);
The first error is because of InputType. It should be int
public class HangfireTestDTO
{
public int InputType { get; set; }
public string Filename { get; set; }
}
The second error is because of JSON. There is an addition quotation between [ and {. I have tried with below JSON and it worked. Because of this quotation it becomes List<string> and not List<HangfireTestDTO>
[
{
"InputType": 12,
"EngineSubType": 2,
"Filename": "targetFile.csv",
"FileExtensionType": ".csv",
"IsLoadFile": true,
"LoadContextId": 4120,
"ReportingDate": "2019-05-31T00:00:00",
"IsSuccess": false
}
]
And looking at the JSON it should be IEnumerable<HangfireTestDTO>
var arguments = JsonSerializer.Deserialize<IEnumerable<HangfireTestDTO>>(data);
var data2 = results.FormData["model2"];
Below is the sample output came from angular json data2 to convert in asp.net MVC web api
{
"0":{"RowStamp":2,"Department":"Billing and Collection"},
"1":{"RowStamp":7,"Department":"Business Development"},
"2":{"RowStamp":10,"Department":"Construction Management/Design"}
}
I have model class
public class DeptModel
{
public int RowStamp { get; set; }
public string Department { get; set; }
}
var dictionary = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<DeptModel>(data2);
Error occured during debugging
Cannot deserialize the current JSON object (e.g. {\"name\":\"value\"}) into type 'System.Collections.Generic.List
Can someone help me to deserialize this to model? Much better if sample code provided. Thanks in advance
This issue resolve the problem
Model
public class DeptModel
{
public int RowStamp { get; set; }
public string Department { get; set; }
}
Deserialize to model
var data2 = results.FormData["model2"];
var dictionary = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<Dictionary<string, DeptModel>>(data2);
In usings section add
using Newtonsoft.Json.Linq;
And use following code:
var request = JArray.Parse(data2);
var dictionaryResult = keyResponse.ToObject<List<Dictionary<string, DeptModel>>>();
This way you can deserialize your JSON with Newtonsoft.Json
const string json = #"
{
""0"":{""RowStamp"":2,""Department"":""Billing and Collection""},
""1"":{""RowStamp"":7,""Department"":""Business Development""},
""2"":{""RowStamp"":10,""Department"":""Construction Management/Design""}
}";
Dictionary<string, DeptModel> dictionary = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, DeptModel>>(json);
I am returning a json string to a WebMethod in WebForms and I want to take the json string and parse it into custom Order objects.
I have a class:
public class Order
{
public string Item { get; set; }
public string Color { get; set; }
public string Qty { get; set; }
public string Size { get; set; }
}
And a WebMethod:
[WebMethod]
public static string SendOrder(string json)
{
List<Order> orders = new List<Order>();
return json;
}
I am passing this string:
{
json: [
{
"Item":"Nike Polo #286772 - Women's Dri-FIT Micro Pique Short Sleeved Polo",
"Size":"XL",
"Color":"Light Blue",
"Quantity":"3"
},
{
"Item":"Port Authority Women's Jacket #L790 - Black",
"Size":"Medium",
"Color":"Black",
"Quantity":"3"
}
]
}
I want to loop through this string and creating new Orders.
What is the best way to do this?
That JSON is a little oddly formatted as it maps to the following classes (using http://json2csharp.com):
public class Json
{
public string Item { get; set; }
public string Size { get; set; }
public string Color { get; set; }
public string Quantity { get; set; }
}
public class RootObject
{
public List<Json> json { get; set; }
}
I'm not sure why you have a top-level variable named json, but whatever.
At this point just use JSON.NET to deserialize into the structure.
JsonConvert.DeserializeObject<RootObject>(yourJsonString);
If you want to rename the object from Json to Order you'll need to use an attribute for that. I don't recall the name off the top of my head but it should be easy to find in the JSON.NET documentation.
I recently completed a Windows Phone app that retrieved info from a Web API-based server as Json strings. I ended up using the JsonConvert class to convert my lists of objects from Json strings to my custom objects. Here's an example of one of my client-side methods that receives and converts the Json strings:
public async void GetGames()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("base url");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync("specific url extention (like api/Order)");
if (response.IsSuccessStatusCode)
{
string s = await response.Content.ReadAsStringAsync();
var deserializedResponse = JsonConvert.DeserializeObject<List<Order>>(s);
//rest of code
}
}
}
Also, make sure that your web method is actually doing something. The example web method you posted creates creates a new list then just returns the parameter you passed in. Using Web API, you could return a list of all Order objects in your database via a method similar to the following:
public IQueryable<Order> GetOrders()
{
return db.Orders; //db is an instance of your DbContext class
}
I hope this is helpful. Let me know if you have any questions.
This is my first try to deserialize a JSON string returned by Facebook.
I want to make sure future developers can maintain my code comfortably so I would like to know if this is okay way to do it. I am concerned that if the JSON string change then I will need to rewrite some of my classes.
Is the JSON string returned from Facebook likely to change? For example if location became a different object I will need to make changes right?
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Web;
//--- If you are not able to add reference dont worry. You probably need to install ASP.NET Ajax or target higher .NET Framework (3.5 or 4).
//--- There are Stack Overflow threads about this.
using System.Web.Script.Serialization;
//--- Our Facebook Person class.
public class FBPerson
{
public string id { get; set; }
public string email { get; set; }
public string name { get; set; }
public string gender { get; set; }
public IDName location { get; set; }
public List<FBObject> work { get; set; }
public List<FBObject> education { get; set; }
}
//-- In some cases only id and name will be accessed
public class IDName
{
public string id { get; set; }
public string name { get; set; }
public string type { get; set; }
}
//-- work and education presently are array of json strings
public class FBObject
{
public IDName employer { get; set; }
public IDName school { get; set; }
}
static class Program
{
//-- Sample JSON string returned by Facebook
const string json2 = #"{
""id"":""11111111111111111"",
""name"":""Tester Test"",
""first_name"":""Tester"",
""last_name"":""Test"",
""link"":""http:\/\/www.facebook.com\/profile.php?id=11111111111111111"",
""location"":
{""id"":""107991659233606"",""name"":""Atlanta, Georgia""},
""work"":
[{""employer"":{""id"":""222222222222222222"",""name"":""Various""}}],
""education"":
[
{""school"":{""id"":""108000000000000"",""name"":""Test High School""},""type"":""High School""},
{""school"":{""id"":""105000000000000"",""name"":""Tester College""},""type"":""College""}
],
""gender"":""male"",
""email"":""tester\u0040gmail.com"",
""timezone"":-5,""locale"":""en_US"",
""verified"":true,
""updated_time"":""2011-11-21T21:10:20+0000""
}";
static void Main()
{
JavaScriptSerializer ser = new JavaScriptSerializer();
FBPerson fperson = ser.Deserialize<FBPerson>(json2);
//-- Display the user info from the JSON string
Console.WriteLine(fperson.id.ToString());
Console.WriteLine(fperson.name.ToString());
Console.WriteLine(fperson.gender.ToString());
Console.WriteLine(fperson.email.ToString());
Console.WriteLine(fperson.location.name.ToString());
Console.WriteLine(fperson.work[0].employer.name.ToString());
Console.WriteLine(fperson.education[0].school.name.ToString());
Console.ReadLine();
}
}
This seems fine. No matter how you do deserialization, changes to the JSON data format would break you. For that reason, API authors try very hard to avoid making such changes.
I don't know whether you are open to other approaches but in case you may want to try,
here is an alternative way that doesn't need FBPerson IDName FBObject classes and makes use of Json.Net and this extension methods
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
static class Program
{
//-- Sample JSON string returned by Facebook
const string json2 = #"{
""id"":""11111111111111111"",
""name"":""Tester Test"",
""first_name"":""Tester"",
""last_name"":""Test"",
""link"":""http:\/\/www.facebook.com\/profile.php?id=11111111111111111"",
""location"":
{""id"":""107991659233606"",""name"":""Atlanta, Georgia""},
""work"":
[{""employer"":{""id"":""222222222222222222"",""name"":""Various""}}],
""education"":
[
{""school"":{""id"":""108000000000000"",""name"":""Test High School""},""type"":""High School""},
{""school"":{""id"":""105000000000000"",""name"":""Tester College""},""type"":""College""}
],
""gender"":""male"",
""email"":""tester\u0040gmail.com"",
""timezone"":-5,""locale"":""en_US"",
""verified"":true,
""updated_time"":""2011-11-21T21:10:20+0000""
}";
public static void Main()
{
dynamic fperson = JsonUtils.JsonObject.GetDynamicJsonObject(json2);
//-- Display the user info from the JSON string
Console.WriteLine(fperson.id.ToString());
Console.WriteLine(fperson.name.ToString());
Console.WriteLine(fperson.gender.ToString());
Console.WriteLine(fperson.email.ToString());
Console.WriteLine(fperson.location.name.ToString());
Console.WriteLine(fperson.work[0].employer.name.ToString());
Console.WriteLine(fperson.education[0].school.name.ToString());
Console.ReadLine();
}
}