How to generate Xml or Json Output Format from Xml raw string? - c#

I'm trying to make use of FormatFilter to generate 'json' or 'xml' controller response output.
The problem is that my starting point it's a random (well-formed) xml string.
I'm using DotNet Core 2.2 and this is what I have right now in controller:
[HttpGet("values.{format}"), FormatFilter]
public ActionResult TestObjectOutput()
{
string xml = DynamicXmlRawString();
XDocument doc = XDocument.Parse(xml);
string json = JsonConvert.SerializeXNode(doc);
dynamic obj = JsonConvert.DeserializeObject<ExpandoObject>(json);
return Ok(obj);
}
public static string DynamicXmlRawString()
{
return $#"<Result><DateTime>{DateTime.Now}</DateTime><User><Someone>12345678</Someone></User></Result>";
}
The output response for json is coming as expected.
$ curl -i -X GET http://0.0.0.0:5000/api/values/object.json
{"Result":{"DateTime":"27/04/2019 16:31:27","User":{"Someone":"12345678"}}}
The response for xml returns HTTP/1.1 406 Not Acceptable
curl -i -X GET http://0.0.0.0:5000/api/values/object.xml
Server error:
An error occurred while trying to create an XmlSerializer for the type 'System.Dynamic.ExpandoObject'.
Expected result:
<Result><DateTime>27/04/2019 16:40:05</DateTime><User><Someone>12345678</Someone></User></Result>
Any idea how to solve this?
Thanks

Seems like I was overthinking...problem solved.
[HttpGet("values.{format}"), FormatFilter]
public ActionResult TestObjectOutput()
{
string xml = DynamicXmlRawString();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
return Ok(xmlDoc);
}
public static string DynamicXmlRawString()
{
return $#"<Result><DateTime>{DateTime.Now}</DateTime><User><Someone>12345678</Someone></User></Result>";
}

Related

XML deserialization: Data at the root level is invalid. Line 1 position 1. Tried almost everything

I'm trying to deserialize XML. I'm getting the XML to string(which works fine) but then when I try to parse it I'm getting and error "Data at the root level is invalid. Line 1 position 1"
I tried everything which I found here. Read a lot of threads and tried all the suggestion: reading this to byte array, to stream, trying different Xml classes, removing BOM.
Here is my code(you can see the XML file under the link in code):
public class XmlParser
{
private List<CurrencyUnit> _currenciesList = new List<CurrencyUnit>();
public List<CurrencyUnit> CurrenciesList { get => _currenciesList; set => _currenciesList = value; }
public async void GetXML()
{
Uri uri = new Uri("http://api.nbp.pl/api/exchangerates/tables/A/");
HttpClient client = new HttpClient();
HttpResponseMessage httpResponse = await client.GetAsync(uri);
string response = await httpResponse.Content.ReadAsStringAsync();
XDocument xDocument = XDocument.Parse(response);
foreach (var element in xDocument.Descendants("Rate"))
{
CurrencyUnit unit = new CurrencyUnit();
unit.Currency = element.Element("Currency").Value.ToString();
unit.Code = element.Element("Code").Value.ToString();
unit.Mid = element.Element("Mid").Value.ToString();
CurrenciesList.Add(unit);
}
}
}
Here is part of the XML(you can see whole under the link from code):
<?xml version="1.0" encoding="UTF-8"?>
<ArrayOfExchangeRatesTable xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ExchangeRatesTable>
<Table>A</Table>
<No>056/A/NBP/2018</No>
<EffectiveDate>2018-03-20</EffectiveDate>
<Rates>
<Rate>
<Currency>bat (Tajlandia)</Currency>
<Code>THB</Code>
<Mid>0.1100</Mid>
</Rate>
That endpoint returns JSON if the request headers don't explicitly ask for XML, and you can't parse JSON as XML.
Your browser sends something like Accept: text/html,[...]application/xml by default, whereas HttpClient sends none. In that case, you get JSON in return. You could've seen this if you'd inspected the response variable while debugging.
Either deserialize the response into JSON, or pass the Accept: application/xml request header as explained in Forcing HttpClient to use Content-Type: text/xml.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));

Converting from JSON to XML using 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

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>

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