Converting from JSON to XML using c# - c#

i have kind of wired requirement for converting JSON to xml.
we have an API that returns the JSON response as below.
{
"status":"Error",
"errorMessages":{
"1001":"Schema validation Error"
}
}
We want to convert this JSON to XML as below using c#
<root>
<status>ERROR</status>
<errorMessages>
<ErrorCode>1001</ErrorCode>
<ErrorDescription>Schema validation Error</ErrorDescription>
</errorMessages>
</root>
The API team is very resistant to change the way there are generating the JSON. So i have to find a way to convert this json to XML.
I am getting the below error when i try to convert
XmlDocument doc = JsonConvert.DeserializeXmlNode(json);
"JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName. Path errorMessages
thanks for the help in advance. :)

At first, I would hardly recommend that your API team provides a valid JSON object. Otherwise you will have to write a converter that does the job. The converter could look like this:
using System.Collections.Generic;
namespace Json
{
using System.IO;
using System.Xml.Serialization;
using Newtonsoft.Json.Linq;
class Program
{
static void Main(string[] args)
{
var converter = new Converter();
converter.Convert();
}
}
class Converter
{
public void Convert()
{
// your JSON string goes here
var jsonString = #"{""status"":""Error"",""errorMessages"":{ ""1001"":""Schema validation Error"", ""1953"":""Another error""}}";
// deconstruct the JSON
var jObject = JObject.Parse(jsonString);
var root = new Root { Status = jObject["status"].ToString(), ErrorMessages = new List<ErrorMessage>() };
foreach (var errorMessageJsonObject in jObject["errorMessages"])
{
var jProperty = (JProperty)errorMessageJsonObject;
var errorCode = System.Convert.ToInt16(jProperty.Name);
var errorDescription = jProperty.Value.ToString();
var errorMessage = new ErrorMessage() { ErrorCode = errorCode, ErrorDescription = errorDescription};
root.ErrorMessages.Add(errorMessage);
}
// serialize as XML
var xmlSerializer = new XmlSerializer(typeof(Root));
string xml;
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, root);
xml = textWriter.ToString();
}
}
}
public class Root
{
public string Status;
public List<ErrorMessage> ErrorMessages;
}
public class ErrorMessage
{
public int ErrorCode;
public string ErrorDescription;
}
}
With this, you will read the JSON, deconstruct it into a proper object and serialize it as XML.

if you are using asp.net web api. Its already can return xml response just add an accept header like
Accept: application/xml

From the documentation at https://www.newtonsoft.com/json/help/html/ConvertingJSONandXML.htm
string json = #"{
'?xml': {
'#version': '1.0',
'#standalone': 'no'
},
'root': {
'person': [
{
'#id': '1',
'name': 'Alan',
'url': 'http://www.google.com'
},
{
'#id': '2',
'name': 'Louis',
'url': 'http://www.yahoo.com'
}
]
}
}";
XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json);

Use the JsonConvert class which contains helper methods for this precise purpose:
// To convert an XML node contained in string xml into a JSON string
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);
// To convert JSON text contained in string json into an XML node
XmlDocument doc = JsonConvert.DeserializeXmlNode(json);
The Completed Documentation : Here

Related

JsonDeserializer check before try to convert Model

Read simple api call code bellow. Here i am getting call response in- IRestResponse response and its a json response. Then using JsonDeserializer() i am trying to convert it to a C# Model which is WallMartData model. ( i think i dont need to share model code here bcoz it doesn't matter for this question ). Now from this same response sometime i will get a json response which match with my model WallMartData and some time it will return other json response. Now my question is- before i try to convert my json response to WallMartData Model i want to check if this is a valid convertable json. If its not valid convartable for this WallMartData model then it will skip try to convert. Bcoz when its fails to convert i am getting invalid json exception on c#. Thats why i need to check before try to convert. Any solution?
string url = "http://api.example.com/v1/items?apiKey=" + Token + "&upc=" + UPC;
var client = new RestClient(url);
var request = new RestRequest(Method.GET);
IRestResponse response = client.Execute(request);
var deserializer = new JsonDeserializer();
var wmr = deserializer.Deserialize<WallMartData>(response);
You can try to create a method use try .... catch to check the JSON string is or isn't valid.
private static bool IsValidJson<T>(string strInput,out T obj)
{
obj = default(T);
try
{
obj = JsonConvert.DeserializeObject<T>(strInput);
return true;
}
catch (JsonReaderException jex)
{
return false;
}
catch (Exception ex)
{
return false;
}
}
Then you can use bool to check the DeserializeObject whether success.
WallMartData wmr;
if(IsValidJson<WallMartData>(response,out wmr)){
//... your logic with wmr
}
I think you can just use try catch block and it will be enough. But if you really need to validate your JSON, you can use JSON Schema. You can generate schema for your class using JsonSchemaGenerator
I suggest using JsonSchema by Json.Net
more info here
let's say that your WallMartData class looks like this
public class WallMartData
{
[JsonProperty("email", Required = Required.Always)]
public string Email;
[JsonProperty("first_name")]
public string firstName;
[JsonProperty("last_name")]
public string lastName;
}
Then you can easily use the schema checker
JSchemaGenerator generator = new JSchemaGenerator();
JSchema schema = generator.Generate(typeof(WallMartData));
string json = #"...";
JObject wallMartData = JObject.Parse(json);
if(wallMartData.IsValid(schema))
{
//if json matching the schema aka the class account
}
else
{
//the json is invalid
}

Hook OData's $metadata response and convert it from XML to JSON

The answer of Get OData $metadata in JSON format states that OData cannot return the metadata as JSON by default.
But is it possible then to capture or hook its response for the $metadata URL, and then convert it on the fly to JSON before sending it to the client?
I imagine pseudocode like this:
[HttpGet]
[ODataRoute("$metadata")]
public string GetMetadataAsJson()
{
string xml = GetOdataMetadataAsXML();
string json = ConvertToJson(xml);
return json;
}
I don't know how to implement it correctly, though, in particular I'm not sure how to get the standard OData response as a string, and how to hook the $metadata URL.
Newtonsoft supports the Json part checkout https://www.newtonsoft.com/json/help/html/ConvertXmlToJson.htm
So the actual solution for the Json Part would be quite simple, as soon as you have your XML
[HttpGet]
[ODataRoute("$metadata")]
public string GetMetadataAsJson()
{
string xml = GetOdataMetadataAsXML();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string json = JsonConvert.SerializeXmlNode(doc);
return json;
}
Also you should probably first check if e.g. a format query is set for example with this code
[HttpGet]
[ODataRoute("$metadata")]
public string GetMetadataAsJson([FromQuery(Name="Format")]string format)
{
string metaResult = GetOdataMetadataAsXML();
if(format.Equals("json",StringComparison.OrdinalIgnoreCase))
{
XmlDocument metaDoc = new XmlDocument();
doc.LoadXml(metaResult);
metaResult = JsonConvert.SerializeXmlNode(doc);
}
return metaResult;
}

send list<xmldocument> to wcf, how to do it?

I'm trying to send List to wcf.
i want to send it as json, is there a way ?
when I'm trying to serialize, i get empty string, why ?
public string ImportXml(List<XmlDocument> docs,string token)
{
Account user = GetCurrentUser(token);
string url = string.Format("{0}ImportXml/{1}", ServiceUrl, user.Unumber);
string contentType = "text/json";
x.Serialize(Console.Out, docs);
string jsonReq = _serializer.Serialize(docs);
bool response = false;
HttpRequestHandler handler = new HttpRequestHandler();
string result = handler.HttpPostWithToken(url, jsonReq, contentType, token);
return result ;
}
Each element of the collection docs before sending into WCF is must be serialized into the JSON for example in this way:
string jsonText = JsonConvert.SerializeXmlNode(doc);
where doc is XmlDocument.
Or for Javascript in this way: Converting between XML and JSON
After you get collection of XmlDocument into WCF method try convert each element of entrance collection:
var documents = new List<XmlDocument>();
foreach (var doc in docs)
{
XmlDocument xmlDoc = JsonConvert.DeserializeXmlNode(doc);
documents.Add(xmlDoc);
}
finnally i got list of strings with xml in it.
it is much better, because that way we can work with anyone, and not only C#.
and i moved to newtonsoft instead JSS.
List<string>

RestSharp XML Deserialization into List

I am trying to deserialize the following xml using RestSharp, but I always get a list of null elements. I am new to REST based services and need some expert help! =)
Solution Found: I figured it out. You have to explicitly tell RestSharp what kind of data is being deserialized:
request.OnBeforeDeserialization = resp => {
resp.ContentType = "application/json";
};
Full XML: http://autocomplete.wunderground.com/aq?query=San%20F&format=xml
Some of the XML is below:
<RESULTS>
<name>San Francisco, California</name>
<type>city</type>
<c>US</c>
<zmw>94101.1.99999</zmw>
<tz>America/Los_Angeles</tz>
<tzs>PDT</tzs>
<l>/q/zmw:94101.1.99999</l>
</RESULTS>
Here is my XMLResults class:
public class XMLResults
{
public List<name> names {get; set;}
}
public class name
{
public string city {get; set;}
}
And here is my getWeather method:
public void getWeather(string query)
{
var client = new RestClient ();
var request = new RestRequest(Method.GET);
client.BaseUrl = "http://autocomplete.wunderground.com";
request.Resource = "aq";
request.AddParameter ("query", query);
request.AddParameter ("format", "xml");
request.RequestFormat = DataFormat.Xml;
var city = client.Execute<XMLResults>(request);
Console.WriteLine (city.Data.names.Count); // Results in 20
}
If it were me I would take a valid XML response ( like the one you posted ) and create a class from it using the xsd.exe program that comes with Visual Studio (it is VS Command Line Tool)
Generate C# class from XML
Then you can easily Serialize and Deserialize your Object.
I had to explicitly tell RestSharp what kind of data is being deserialized: request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json";};

Converting JSON to XML

I trying to convert JSON output into XML. Unfortunately I get this error:
JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifing a DeserializeRootElementName.
This is what I up to now created.
string url = string.Format("https://graph.facebook.com/{0}?fields=posts.fields(message)&access_token={1}", user_name, access_token);
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
jsonOutput = reader.ReadToEnd();
Console.WriteLine("THIS IS JSON OUTPUT: " + jsonOutput);
}
XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(jsonOutput);
Console.WriteLine(doc);
And this is my JSON output:
{"id":"108013515952807","posts":{"data":[{"id":"108013515952807_470186843068804","created_time":"2013-05-14T20:43:28+0000"},{"message":"TEKST","id":"108013515952807_470178529736302","created_time":"2013-05-14T20:22:07+0000"}
How can I solve this problem?
Despite the fact your JSON provided in the question is not complete, you have multiple properties at the top level as indicated by the exception. You have to define the root for it to get valid XML:
var doc = JsonConvert.DeserializeXmlNode(jsonOutput, "root");
EDIT: In order to print out your XML with indentation you can use XDocument class from System.Xml.Linq namespace: XDocument.Parse(doc.InnerXml).
I thought it's worth linking to the Documentation for turning xml to json and the other way around.
The guys are right..
// To convert an XML node contained in string xml into a JSON string
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
string jsonText = JsonConvert.SerializeXmlNode(doc);
// To convert JSON text contained in string json into an XML node
XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(json);
You can do JSON-to-XML also by using the .NET Framework (System.Runtime.Serialization.Json):
private static XDocument JsonToXml(string jsonString)
{
using (var stream = new MemoryStream(Encoding.ASCII.GetBytes(jsonString)))
{
var quotas = new XmlDictionaryReaderQuotas();
return XDocument.Load(JsonReaderWriterFactory.CreateJsonReader(stream, quotas));
}
}
DeserializeXmlNode returns XDcument.
If needed XNode use FirstNode.
//string jsonOutput="{"id":"108013515952807","posts":{"data":[{"id":"108013515952807_470186843068804","created_time":"2013-05-14T20:43:28+0000"},{"message":"TEKST","id":"108013515952807_470178529736302","created_time":"2013-05-14T20:22:07+0000"}";
var myelement= JsonConvert.DeserializeXmlNode(jsonOutput, "myelement").FirstNode;
Your shared JSON is invalid please go through http://jsonformatter.curiousconcept.com/ and validate your JSON first.
Yourt JSON should look like:
{
"id":"108013515952807",
"posts":{
"data":[
{
"id":"108013515952807_470186843068804",
"created_time":"2013-05-14T20:43:28+0000"
},
{
"message":"TEKST",
"id":"108013515952807_470178529736302",
"created_time":"2013-05-14T20:22:07+0000"
}
]
}
}
Adding on #jwaliszko's answer, converting json to XDocument:
XDocument xml = JsonConvert.DeserializeXNode(json);

Categories

Resources