XmlNodeConverter can only convert JSON that begins with an object - c#

My webapi method is:
public JsonResult<List<MyClass>> PullData()
{
List<MyClass> data = new List<MyClass>();
data = db.TableName.Select(x => new MyClass
{
Id = x.Id,
IsActive = x.IsActive,
//other attribute..
}).ToList();
return Json(data);
}
And I'm consuming this webapi as:
public async Task<string> Index()
{
string apiUrl = "http://localhost:90/api/Scheduler/pulldata";
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(apiUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(apiUrl);
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsStringAsync();
JsonConvert.DeserializeXmlNode(data, "root"); //exception: XmlNodeConverter can only convert JSON that begins with an object.
}
}
return "Error";
}
I get error:
XmlNodeConverter can only convert JSON that begins with an object.
Also In api consumption method (i.e, Index) when I debug and see data in var data = await response.Content.ReadAsStringAsync(); as JSON Visualizer it shows data fine.
But when I do XML visualizer, it doesn't show data.
Update:
The data is too large. I can't share it. Here is the screen shot of data.
Update 2:
Here is a part of json data from begining:
[{"LearningActivityKey":2122,"ModuleName":"certName","ModuleVersion":1.0,"ModuleDescription":"<p><span style=\"background-color:rgb(240, 240, 240); font-family:archivo narrow,helvetica,arial,sans-serif; font-size:16px; line-height:20px; white-space:pre-line\">Learn SAP
Update 3:
I have changed the webapi method PullData() to send only two records, so that we can easily visualize wethere the issue is with json data.
Complete data is:
[{"LearningActivityKey":2122,"ModuleName":"certName","ModuleVersion":0.0,"ModuleDescription":null,"BadgeName":null,"BadgeVersion":null,"BadgeDescription":null,"MozillaBadge":null,"LearningActivityName":null,"LearningActivityDescription":null,"StepName":null,"StepVersion":null,"StepDescription":null,"IsActive":false,"IsPublished":false,"CreatedDate":"0001-01-01T00:00:00","ModifiedDate":null},{"LearningActivityKey":2122,"ModuleName":"certName","ModuleVersion":0.0,"ModuleDescription":null,"BadgeName":null,"BadgeVersion":null,"BadgeDescription":null,"MozillaBadge":null,"LearningActivityName":null,"LearningActivityDescription":null,"StepName":null,"StepVersion":null,"StepDescription":null,"IsActive":false,"IsPublished":false,"CreatedDate":"0001-01-01T00:00:00","ModifiedDate":null}]
I pasted data in https://jsonformatter.curiousconcept.com/ and it says:
And XML Visualizer still doesn't show any data.

The exception is self-explanatory: you cannot convert JSON to XML unless the root token is an object, even if you use the JsonConvertDeserializeXmlNode(String, String) method to specify an outer root element name.
As to why this is true, the documentation page Converting between JSON and XML shows that a JSON array is converted to a repeating sequence of XML elements without an added outer container element. I.e. JSON like this (simplified from the documentation):
{
"root": {
"person": [
{
"name": "Alan"
},
{
"name": "Louis"
}
]
}
}
Is converted to XML as follows:
<root>
<person>
<name>Alan</name>
</person>
<person>
<name>Louis</name>
</person>
</root>
Notice that an outer <root> node is created, and a repeated sequence of <person> nodes -- but nothing in between? If there were no outer object with a "root" property in the JSON then Json.NET would have tried to create XML with multiple <person> root elements. This is disallowed by the XML standard which requires exactly one root element. Thus it appears a JSON array must be contained within at least two levels of JSON object nesting to be successfully converted to XML (although one of those levels could come by specifying an outer root element name via JsonConvertDeserializeXmlNode(String, String)).
As a workaround, you can introduce the following extension methods to nest your JSON in an extra level of object.
First, grab ChainedTextReader and public static TextReader Extensions.Concat(this TextReader first, TextReader second) from the answer to How to string multiple TextReaders together? by Rex M. Using them, create the following extension methods:
public static partial class JsonExtensions
{
public static XmlDocument DeserializeXmlNode(string json, string rootName, string rootPropertyName)
{
return DeserializeXmlNode(new StringReader(json), rootName, rootPropertyName);
}
public static XmlDocument DeserializeXmlNode(TextReader textReader, string rootName, string rootPropertyName)
{
var prefix = "{" + JsonConvert.SerializeObject(rootPropertyName) + ":";
var postfix = "}";
using (var combinedReader = new StringReader(prefix).Concat(textReader).Concat(new StringReader(postfix)))
{
var settings = new JsonSerializerSettings
{
Converters = { new Newtonsoft.Json.Converters.XmlNodeConverter() { DeserializeRootElementName = rootName} },
DateParseHandling = DateParseHandling.None,
};
using (var jsonReader = new JsonTextReader(combinedReader) { CloseInput = false, DateParseHandling = DateParseHandling.None })
{
return JsonSerializer.CreateDefault(settings).Deserialize<XmlDocument>(jsonReader);
}
}
}
}
// Taken from
// https://stackoverflow.com/questions/2925652/how-to-string-multiple-textreaders-together/2925722#2925722
public static class Extensions
{
public static TextReader Concat(this TextReader first, TextReader second)
{
return new ChainedTextReader(first, second);
}
private class ChainedTextReader : TextReader
{
private TextReader first;
private TextReader second;
private bool readFirst = true;
public ChainedTextReader(TextReader first, TextReader second)
{
this.first = first;
this.second = second;
}
public override int Peek()
{
if (readFirst)
{
return first.Peek();
}
else
{
return second.Peek();
}
}
public override int Read()
{
if (readFirst)
{
int value = first.Read();
if (value == -1)
{
readFirst = false;
}
else
{
return value;
}
}
return second.Read();
}
public override void Close()
{
first.Close();
second.Close();
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
first.Dispose();
second.Dispose();
}
}
}
}
And convert to XML as follows:
var doc = JsonExtensions.DeserializeXmlNode(data, "root", "array");
Using the JSON from your question, the following XML is generated:
<root>
<array>
<LearningActivityKey>2122</LearningActivityKey>
<ModuleName>certName</ModuleName>
<!-- Additional properties omitted -->
</array>
<array>
<LearningActivityKey>2122</LearningActivityKey>
<ModuleName>certName</ModuleName>
<!-- Additional properties omitted -->
</array>
</root>
Working sample .Net fiddle.

Related

C# XML parsing thru EPPlus

I am parsing XML, I have generated Class from XSD file, I am able to access simple values from XML, but I don't know how to get value from this. I need it as String.
public partial class AccountIdentification4Choice {
private object itemField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("IBAN", typeof(string))]
[System.Xml.Serialization.XmlElementAttribute("Othr", typeof(GenericAccountIdentification1))]
public object Item {
get {
return this.itemField;
}
set {
this.itemField = value;
}
}
}
In XML value can be like this:
<CdtrAcct><Id><Othr><Id>BBAN</Id></Othr></Id></CdtrAcct>
or
<CdtrAcct><Id><IBAN>BBAN</IBAN></Id></CdtrAcct>
Update - all resource files:
XML: Priklad_multi.XML
XSD: camt.053.001.02.xsd
Then I parse XML with EPPlus package:
XmlSerializer ser = new XmlSerializer(typeof(Document));
Document resp = ser.Deserialize(new FileStream(file, FileMode.Open)) as Document;
And then I can access XML values like this (for example Stmt-Acct)
resp.BkToCstmrStmt.Stmt[ind].Acct.Id.Item
But I don't know how to access this CdtrAcct section in same way.
Your question is not clear, but as I understand you want to get IBAN tag, right? If so, you could do that easily with Linq To XML. ie:
void Main()
{
string xml1 = "<CdtrAcct><Id><Othr><Id>BBAN</Id></Othr></Id></CdtrAcct>";
string xml2 = "<CdtrAcct><Id><IBAN>BBAN</IBAN></Id></CdtrAcct>";
Console.WriteLine(CheckIban(xml1));
Console.WriteLine(CheckIban(xml2));
}
private string CheckIban(string xml)
{
var iban = XElement.Parse(xml).DescendantsAndSelf("IBAN").FirstOrDefault();
if (iban != null)
{
return (string)iban;
}
iban = XElement.Parse(xml).DescendantsAndSelf("Othr")
.FirstOrDefault();
if (iban != null)
{
return iban.Element("Id").Value;
}
return null;
}

How to escape embedded JSON after unescape

When serializing with Json.NET, I need to escape embedded JSON after previously unescaping while deserializing. Which means I unescaped following JSON according to this post.
Here is my JSON:
{
"Message":null,
"Error":false,
"VData":{
"RNumber":null,
"BRNumber":"Session1"
},
"onlineFields":{
"CCode":"Web",
"MNumber":"15478655",
"Product":"100",
"JsonFile":" {
\"evaluation\":{
\"number\":[
{
\"#paraID\":\"1000\",
\"#Value\":\"\",
\"#label\":\"We are america\"
},
{
\"#paraID\":\"2000\",
\"#Value\":\"100\",
\"#label\":\"We are japan\"
},
{
\"#paraID\":\"3000\",
\"#Value\":\"1000\",
\"#label\":\"We are UK\"
},
{
\"#paraID\":\"4000\",
\"#Value\":\"\",
\"#label\":\"We are China\"
}
]
}
} "
}
}
After unescaping, I bind the above JSON to my model classes. And it works properly. to Bind JSON to a model I used following code.
private static void showJSON(string testJson){
Response response = JsonConvert.DeserializeObject<Response>(testJson);
var dropdowns = response.OnlineFields.JsonFile;
string json = JsonConvert.SerializeObject(dropdowns, Newtonsoft.Json.Formatting.Indented);
Console.WriteLine(json);
}
After bind JSON to model, there has some logic to set values to JSON and returns unescaped JSON. which means it also returns unescaped JsonFile, I again need above JSON format (escaped embedded JsonFile) to send to the client API.
This is unescaped JSON format, I need convert this to above escaped JSON (escaped embedded JsonFile)
{
"Message":null,
"Error":false,
"VData":{
"RNumber":null,
"BRNumber":"Session1"
},
"onlineFields":{
"CCode":"Web",
"MNumber":"15478655",
"Product":"100",
"JsonFile":{
"evaluation":{
"number":[
{
"#paraID":"1000",
"#Value":"",
"#label":"We are america"
},
{
"#paraID":"2000",
"#Value":"100",
"#label":"We are japan"
},
{
"#paraID":"3000",
"#Value":"1000",
"#label":"We are UK"
},
{
"#paraID":"4000",
"#Value":"",
"#label":"We are China"
}
]
}
}
}
}
Previously I asked a question for how to directly deserialize such embedded JSON into c# classes, but the answer there did not explain how to re-serialize in the same format. I need to extend the answer from that previous question to writing.
You can extend EmbeddedLiteralConverter<T> from this answer to How do I convert an escaped JSON string within a JSON object? by overriding JsonConverter.WriteJson() and doing a nested serialization, then writing the resulting string literal, like so:
public class EmbeddedLiteralConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
using (new PushValue<bool>(true, () => Disabled, (canWrite) => Disabled = canWrite))
{
using (var sw = new StringWriter(writer.Culture))
{
// Copy relevant settings
using (var nestedWriter = new JsonTextWriter(sw)
{
DateFormatHandling = writer.DateFormatHandling,
DateFormatString = writer.DateFormatString,
DateTimeZoneHandling = writer.DateTimeZoneHandling,
StringEscapeHandling = writer.StringEscapeHandling,
FloatFormatHandling = writer.FloatFormatHandling,
Culture = writer.Culture,
// Remove if you don't want the escaped \r\n characters in the embedded JSON literal:
Formatting = writer.Formatting,
})
{
serializer.Serialize(nestedWriter, value);
}
writer.WriteValue(sw.ToString());
}
}
}
[ThreadStatic]
static bool disabled;
// Disables the converter in a thread-safe manner.
bool Disabled { get { return disabled; } set { disabled = value; } }
public override bool CanWrite { get { return !Disabled; } }
public override bool CanRead { get { return !Disabled; } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var contract = serializer.ContractResolver.ResolveContract(objectType);
if (contract is JsonPrimitiveContract)
throw new JsonSerializationException("Invalid type: " + objectType);
if (existingValue == null)
existingValue = contract.DefaultCreator();
if (reader.TokenType == JsonToken.String)
{
var json = (string)JToken.Load(reader);
using (var subReader = new JsonTextReader(new StringReader(json)))
{
// By populating a pre-allocated instance we avoid an infinite recursion in EmbeddedLiteralConverter<T>.ReadJson()
// Re-use the existing serializer to preserve settings.
serializer.Populate(subReader, existingValue);
}
}
else
{
serializer.Populate(reader, existingValue);
}
return existingValue;
}
}
struct PushValue<T> : IDisposable
{
Action<T> setValue;
T oldValue;
public PushValue(T value, Func<T> getValue, Action<T> setValue)
{
if (getValue == null || setValue == null)
throw new ArgumentNullException();
this.setValue = setValue;
this.oldValue = getValue();
setValue(value);
}
#region IDisposable Members
// By using a disposable struct we avoid the overhead of allocating and freeing an instance of a finalizable class.
public void Dispose()
{
if (setValue != null)
setValue(oldValue);
}
#endregion
}
Then, add the converter to JsonSerializerSettings.Converters when deserializing and serializing:
var settings = new JsonSerializerSettings
{
Converters = { new EmbeddedLiteralConverter<JsonFile>() },
};
var response = JsonConvert.DeserializeObject<Response>(testJson, settings);
var json2 = JsonConvert.SerializeObject(response, Formatting.Indented, settings);
Or, you could apply the converter directly to your model using JsonConverterAttribute like so:
public class OnlineFields
{
public string CCode { get; set; }
public string MNumber { get; set; }
public string Product { get; set; }
[JsonConverter(typeof(EmbeddedLiteralConverter<JsonFile>))]
public JsonFile JsonFile { get; set; }
}
Notes:
Your input JSON is, strictly speaking, not well formed. The string value for the property JsonFile contains unescaped carriage return characters:
"JsonFile":" {
\"evaluation\":{
\"number\":[
According to the original JSON proposal as well as JSON RFC 7159 Page 8 such control characters must be escaped:
"{\r\n \"evaluation\": {\r\n \"number\": ..."
To confirm this, you can upload your initial JSON to https://jsonformatter.curiousconcept.com/ which reports the following error:
Invalid JSON (RFC 4627): Error:Invalid characters found.[Code 18, Structure 39]
As it turns out, Json.NET will read such invalid JSON without complaint, but will only write well-formed JSON by correctly escaping the carriage returns and line feeds inside the nested JSON literal. Thus your re-serialized JSON will not look identical to the initial JSON. It will, however, be well-formed, and should be consumable by any JSON parser.
To prevent a stack overflow exception when serializing, EmbeddedLiteralConverter<T>.WriteJson() disables itself when called recursively by using the technique from this answer to JSON.Net throws StackOverflowException when using [JsonConvert()].
Working sample .Net fiddle here.

Parsing CDATA with C# to get BaseCod64

I am trying to get the baseCode64 Data within my response data. I am getting the ReturnCode but how can I get the data inside the "Payload".
For example my response data looks like this:
<xml_response xsi:type="xsd:string"><![CDATA[<CertificateRequest><ReturnCode>0</ReturnCode><Payload content_type="application/pdf" embedded="base64">SGVsbG8gV29ybGQ=</Payload></CertificateRequest>]]></xml_response>
To get the ReturnValue I have coded this:
XElement xmlTree = XElement.Parse(response_data);
XElement returnCode = xmlTree.Element("ReturnCode");
XText returnCode_Value = returnCode.FirstNode as XText;
String b1 = returnCode_Value.Value;
Now, how can I get the Value inside the Payload which I to convert in plaintext or create a pdf.
I tried to use the same way with paylaod but i doesn't work. I am getting nothing:
XElement returnCode = xmlTree.Element("Payload");
An if I display the Elements with:
XElement xmlTree = XElement.Parse(response_data);
XElement new_data = xmlTree.Elements();
I am just getting:
0
I has been displayed the Element Payload. This is very interesting but why?
I would simply read the content of the response using the XmlSerializer, it makes it very easy to read the data into the object, and even the decoding could be done over a hidden property
So to read the certificate request, you could go for the following 2 classes
public class CertificateRequest
{
[XmlElement("ReturnCode")]
public int ReturnCode { get; set; }
[XmlElement("Payload")]
public Payload Payload { get; set; }
}
public class Payload
{
[XmlAttribute("content_type")]
public string ContentType { get; set; }
[XmlAttribute("embedded")]
public string Embedded { get; set; }
[XmlText]
public string Value { get; set; }
[XmlIgnore]
public string DecodedValue
{
get
{
if (string.IsNullOrWhiteSpace(Value))
{
return string.Empty;
}
return System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(Value));
}
}
}
and then read the string using a memorystream to deserialize it to a certificate request object, as in the following way:
class Program
{
static CertificateRequest DeserializeRequest(string content)
{
CertificateRequest request = null;
using (MemoryStream ms = new MemoryStream())
{
byte[] data = System.Text.Encoding.UTF8.GetBytes("<?xml version=\"1.0\" encoding=\"utf-8\"?>" + content);
ms.Write(data, 0, data.Length);
ms.Position = 0;
XmlSerializer xs = new XmlSerializer(typeof(CertificateRequest));
request = xs.Deserialize(ms) as CertificateRequest;
}
return request;
}
static void Main(string[] args)
{
string xmlAsString = #"<CertificateRequest><ReturnCode>0</ReturnCode><Payload content_type=""application/pdf"" embedded=""base64"">SGVsbG8gV29ybGQ=</Payload></CertificateRequest>";
CertificateRequest request = DeserializeRequest(xmlAsString);
Console.WriteLine(request.Payload.Value);
Console.WriteLine(request.Payload.DecodedValue);
Console.ReadLine();
}
}
which would then print the base64 encoded value + Hello world on the second line (good one :D)
You don't show the code where you're attempting to access the value of Payload, so I'm sort of guessing what you want to do, but try this:
XElement payload = xmlTree.Element("Payload");
string b2 = payload.Value;
First off, your XML won't load because it's missing a namespace declaration for xsi. I fixed it by adding the following:
<xml_response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:string" ...
Having done that, your XML contains an embedded text string literal (represented as CDATA) which is itself XML. Therefore you must:
Parse the outer XML.
Extract the character data as a string.
Parse the inner XML.
For instance:
string response_data = #"<xml_response xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xsi:type=""xsd:string""><![CDATA[<CertificateRequest><ReturnCode>0</ReturnCode><Payload content_type=""application/pdf"" embedded=""base64"">SGVsbG8gV29ybGQ=</Payload></CertificateRequest>]]></xml_response>";
var xmlTree = XElement.Parse(response_data);
var innerXml = xmlTree.Value; // Extract the string literal
var innerXmlTree = XElement.Parse(innerXml); // Parse the string literal as XML
var payload = innerXmlTree.Element("Payload").Value; // Extract the payload value
Debug.Assert(payload == "SGVsbG8gV29ybGQ="); // No assert.

Serialization: How to Deserialize in C#

How can I deserialize the string based on what I have done in this method? Basically, what I have here is to pass the string through the network using serialization and deserialize the string in order to convey the message. But once I managed to receive the message, I have no idea if what I'm doing is correct. Here's the code:
string ConvertToString(FrogGame np, Frog1 pm, Frog2 pm2) //Serialization. the three parameters are the classes.
{
XmlSerializer sendSerializer = new XmlSerializer(typeof(FrogGame),new Type[]{typeof(Frog1),typeof(Frog2)});
StreamWriter myWriter = new StreamWriter(#"pad1.xml");
sendSerializer.Serialize(myWriter, np);
sendSerializer.Serialize(myWriter, pm);
sendSerializer.Serialize(myWriter, pm2);
return myWriter.ToString();
} //Overall, I serialize it into string
Once I pass the string through the network, I want to deserialize it in order the pass the message to the classes. How do I continue here onwards? How can I edit? The code:
void StringReceived(string str) //so str is myWriter.ToString()
{
XmlSerializer revSerializer = new XmlSerializer(typeof(FrogGame), new Type[] { typeof(Frog1), typeof(Frog2) });
FileStream myFileStream = new FileStream(#"pad1.xml", FileMode.Open);
FrogGame b = (FrogGame)revSerializer.Deserialize(myFileStream);
if (b is Frog1)
{
if (Network.IsServer())
{
pm = (Frog1)b;
pm.Position.Y = b.pm.Position.Y;
pm.Position.X = b.pm.Position.X;
}
else
{
System.Diagnostics.Debug.WriteLine("BAD Message: " + msg);
}
}
else if (b is Frog2)
{
if (Network.IsClient())
{
pm2 = (PaddleMessage2)b;
pm2.Position.Y = b.pm2.Position.Y;
pm2.Position.X = b.pm2.Position.X;
}
else
{
System.Diagnostics.Debug.WriteLine("BAD Message: " + msg);
}
}
}
I might misinterpret your problem, but I why don't you put all the thing you want to save in a class and do it like this (plus, if you use class, your data "transportation" and "management" will be much easier) :
SERIALIZATION
XmlSerializer serializer = new XmlSerializer(typeof(FrogGameData));
TextWriter textWriter = new StreamWriter("FrogGameSaveFile.xml");
serializer.Serialize(textWriter, _frogGameData);
textWriter.Close();
DESERIALIZATION
XmlSerializer deserializer = new XmlSerializer(typeof(FrogGameData));
TextReader textReader = new StreamReader("FrogGameSaveFile.xml");
_frogGameData = (FrogGameData)deserializer.Deserialize(textReader);
textReader.Close();
Note : The need-to-be-saved field should have property, because the tag in the XML will mimic the property name.
Additional Note : FrogGameData is not different than a normal class for automatic serialization like this. The XML will mimic your property order in the class for the one in the XML file.
But if you wanna need to rearrange the XML tag placement, you could do something like [XmlElement(Order = 1)],[XmlElement(Order = 2)], etc on top of your property to customize the order in XML file.
UPDATE
In case you need it, this is an example of your FrogGameData class :
public class FrogGameData
{
private Frog _frog1;
private Frog _frog2;
public Frog Frog1
{
get { return _frog1; }
set { _frog1 = value; }
}
public Frog Frog2
{
get { return _frog2; }
set { _frog2 = value; }
}
}
And the XML will pretty much like this :
<?xml version="1.0" encoding="utf-8"?>
<FrogGameData>
<Frog1>Something-depends-on-your-data</Frog1>
<Frog2>Something-depends-on-your-data</Frog2>
</FrogGameData>
But, if your class is (Note the XmlElement part) :
public class FrogGameData
{
private Frog _frog1;
private Frog _frog2;
[XmlElement(Order = 2)]
public Frog Frog1
{
get { return _frog1; }
set { _frog1 = value; }
}
[XmlElement(Order = 1)]
public Frog Frog2
{
get { return _frog2; }
set { _frog2 = value; }
}
}
Then, your XML will be :
<?xml version="1.0" encoding="utf-8"?>
<FrogGameData>
<Frog2>Something-depends-on-your-data</Frog2>
<Frog1>Something-depends-on-your-data</Frog1>
</FrogGameData>

Convert JSON String To C# Object

Trying to convert a JSON string into an object in C#. Using a really simple test case:
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
object routes_list = json_serializer.DeserializeObject("{ \"test\":\"some data\" }");
The problem is that routes_list never gets set; it's an undefined object. Any ideas?
Or, you can use the Newtownsoft.Json library as follows:
using Newtonsoft.Json;
...
var result = JsonConvert.DeserializeObject<T>(json);
Where T is your object type that matches your JSON string.
It looks like you're trying to deserialize to a raw object. You could create a Class that represents the object that you're converting to. This would be most useful in cases where you're dealing with larger objects or JSON Strings.
For instance:
class Test {
String test;
String getTest() { return test; }
void setTest(String test) { this.test = test; }
}
Then your deserialization code would be:
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
Test routes_list =
(Test)json_serializer.DeserializeObject("{ \"test\":\"some data\" }");
More information can be found in this tutorial:
http://www.codeproject.com/Tips/79435/Deserialize-JSON-with-Csharp.aspx
You probably don't want to just declare routes_list as an object type. It doesn't have a .test property, so you really aren't going to get a nice object back. This is one of those places where you would be better off defining a class or a struct, or make use of the dynamic keyword.
If you really want this code to work as you have it, you'll need to know that the object returned by DeserializeObject is a generic dictionary of string,object. Here's the code to do it that way:
var json_serializer = new JavaScriptSerializer();
var routes_list = (IDictionary<string, object>)json_serializer.DeserializeObject("{ \"test\":\"some data\" }");
Console.WriteLine(routes_list["test"]);
If you want to use the dynamic keyword, you can read how here.
If you declare a class or struct, you can call Deserialize instead of DeserializeObject like so:
class MyProgram {
struct MyObj {
public string test { get; set; }
}
static void Main(string[] args) {
var json_serializer = new JavaScriptSerializer();
MyObj routes_list = json_serializer.Deserialize<MyObj>("{ \"test\":\"some data\" }");
Console.WriteLine(routes_list.test);
Console.WriteLine("Done...");
Console.ReadKey(true);
}
}
Using dynamic object with JavaScriptSerializer.
JavaScriptSerializer serializer = new JavaScriptSerializer();
dynamic item = serializer.Deserialize<object>("{ \"test\":\"some data\" }");
string test= item["test"];
//test Result = "some data"
Newtonsoft is faster than java script serializer. ... this one depends on the Newtonsoft NuGet package, which is popular and better than the default serializer.
one line code solution.
var myclass = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(Jsonstring);
Myclass oMyclass = Newtonsoft.Json.JsonConvert.DeserializeObject<Myclass>(Jsonstring);
You can accomplished your requirement easily by using Newtonsoft.Json library. I am writing down the one example below have a look into it.
Class for the type of object you receive:
public class User
{
public int ID { get; set; }
public string Name { get; set; }
}
Code:
static void Main(string[] args)
{
string json = "{\"ID\": 1, \"Name\": \"Abdullah\"}";
User user = JsonConvert.DeserializeObject<User>(json);
Console.ReadKey();
}
this is a very simple way to parse your json.
Here's a simple class I cobbled together from various posts.... It's been tested for about 15 minutes, but seems to work for my purposes. It uses JavascriptSerializer to do the work, which can be referenced in your app using the info detailed in this post.
The below code can be run in LinqPad to test it out by:
Right clicking on your script tab in LinqPad, and choosing "Query
Properties"
Referencing the "System.Web.Extensions.dll" in "Additional References"
Adding an "Additional Namespace Imports" of
"System.Web.Script.Serialization".
Hope it helps!
void Main()
{
string json = #"
{
'glossary':
{
'title': 'example glossary',
'GlossDiv':
{
'title': 'S',
'GlossList':
{
'GlossEntry':
{
'ID': 'SGML',
'ItemNumber': 2,
'SortAs': 'SGML',
'GlossTerm': 'Standard Generalized Markup Language',
'Acronym': 'SGML',
'Abbrev': 'ISO 8879:1986',
'GlossDef':
{
'para': 'A meta-markup language, used to create markup languages such as DocBook.',
'GlossSeeAlso': ['GML', 'XML']
},
'GlossSee': 'markup'
}
}
}
}
}
";
var d = new JsonDeserializer(json);
d.GetString("glossary.title").Dump();
d.GetString("glossary.GlossDiv.title").Dump();
d.GetString("glossary.GlossDiv.GlossList.GlossEntry.ID").Dump();
d.GetInt("glossary.GlossDiv.GlossList.GlossEntry.ItemNumber").Dump();
d.GetObject("glossary.GlossDiv.GlossList.GlossEntry.GlossDef").Dump();
d.GetObject("glossary.GlossDiv.GlossList.GlossEntry.GlossDef.GlossSeeAlso").Dump();
d.GetObject("Some Path That Doesnt Exist.Or.Another").Dump();
}
// Define other methods and classes here
public class JsonDeserializer
{
private IDictionary<string, object> jsonData { get; set; }
public JsonDeserializer(string json)
{
var json_serializer = new JavaScriptSerializer();
jsonData = (IDictionary<string, object>)json_serializer.DeserializeObject(json);
}
public string GetString(string path)
{
return (string) GetObject(path);
}
public int? GetInt(string path)
{
int? result = null;
object o = GetObject(path);
if (o == null)
{
return result;
}
if (o is string)
{
result = Int32.Parse((string)o);
}
else
{
result = (Int32) o;
}
return result;
}
public object GetObject(string path)
{
object result = null;
var curr = jsonData;
var paths = path.Split('.');
var pathCount = paths.Count();
try
{
for (int i = 0; i < pathCount; i++)
{
var key = paths[i];
if (i == (pathCount - 1))
{
result = curr[key];
}
else
{
curr = (IDictionary<string, object>)curr[key];
}
}
}
catch
{
// Probably means an invalid path (ie object doesn't exist)
}
return result;
}
}
As tripletdad99 said
var result = JsonConvert.DeserializeObject<T>(json);
but if you don't want to create an extra object you can make it with Dictionary instead
var result = JsonConvert.DeserializeObject<Dictionary<string, string>>(json_serializer);
add this ddl to reference to your project: System.Web.Extensions.dll
use this namespace: using System.Web.Script.Serialization;
public class IdName
{
public int Id { get; set; }
public string Name { get; set; }
}
string jsonStringSingle = "{'Id': 1, 'Name':'Thulasi Ram.S'}".Replace("'", "\"");
var entity = new JavaScriptSerializer().Deserialize<IdName>(jsonStringSingle);
string jsonStringCollection = "[{'Id': 2, 'Name':'Thulasi Ram.S'},{'Id': 2, 'Name':'Raja Ram.S'},{'Id': 3, 'Name':'Ram.S'}]".Replace("'", "\"");
var collection = new JavaScriptSerializer().Deserialize<IEnumerable<IdName>>(jsonStringCollection);
Copy your Json and paste at textbox on json2csharp and click on Generate button.
A cs class will be generated use that cs file as below
var generatedcsResponce = JsonConvert.DeserializeObject(yourJson);
Where RootObject is the name of the generated cs file;
Another fast and easy way to semi-automate these steps is to:
take the JSON you want to parse and paste it here: https://app.quicktype.io/ . Change language to C# in the drop down.
Update the name in the top left to your class name, it defaults to "Welcome".
In visual studio go to Website -> Manage Packages and use NuGet to add Json.Net from Newtonsoft.
app.quicktype.io generated serialize methods based on Newtonsoft.
Alternatively, you can now use code like:
WebClient client = new WebClient();
string myJSON = client.DownloadString("https://URL_FOR_JSON.com/JSON_STUFF");
var myClass = Newtonsoft.Json.JsonConvert.DeserializeObject(myJSON);
Convert a JSON string into an object in C#. Using below test case.. its worked for me. Here "MenuInfo" is my C# class object.
JsonTextReader reader = null;
try
{
WebClient webClient = new WebClient();
JObject result = JObject.Parse(webClient.DownloadString("YOUR URL"));
reader = new JsonTextReader(new System.IO.StringReader(result.ToString()));
reader.SupportMultipleContent = true;
}
catch(Exception)
{}
JsonSerializer serializer = new JsonSerializer();
MenuInfo menuInfo = serializer.Deserialize<MenuInfo>(reader);
First you have to include library like:
using System.Runtime.Serialization.Json;
DataContractJsonSerializer desc = new DataContractJsonSerializer(typeof(BlogSite));
string json = "{\"Description\":\"Share knowledge\",\"Name\":\"zahid\"}";
using (var ms = new MemoryStream(ASCIIEncoding.ASCII.GetBytes(json)))
{
BlogSite b = (BlogSite)desc.ReadObject(ms);
Console.WriteLine(b.Name);
Console.WriteLine(b.Description);
}
Let's assume you have a class name Student it has following fields and it has a method which will take JSON as a input and return a string Student Object.We can use JavaScriptSerializer here Convert JSON String To C# Object.std is a JSON string here.
public class Student
{
public string FirstName {get;set:}
public string LastName {get;set:}
public int[] Grades {get;set:}
}
public static Student ConvertToStudent(string std)
{
var serializer = new JavaScriptSerializer();
Return serializer.Deserialize<Student>(std);
}
Or, you can use the System.Text.Json library as follows:
using System.Text.Json;
...
var options = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
});
var result = JsonSerializer.Deserialize<List<T>>(json, options);
Where T is your object type that matches your JSON string.
System.Text.Json is available in:
.NET Core 2.0 and above
.NET Framework 4.6.1 and above

Categories

Resources