我的webapi方法是:
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);
}
我正在使用这个webapi:
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";
}
我收到错误:
XmlNodeConverter只能转换以对象开头的JSON。
同样在api消费方法(即Index
)中,当我调试var data = await response.Content.ReadAsStringAsync();
中的数据为JSON Visualizer
时,它显示数据正常。
更新2:
以下是来自开头的json数据的一部分:
[{"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
更新3:
我已经更改了webapi方法PullData()
以仅发送两条记录,因此我们可以轻松地将问题视为json数据的问题。
完整的数据是:
[{"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}]
我在https://jsonformatter.curiousconcept.com/粘贴了数据,并说:
XML Visualizer
仍然没有显示任何数据。
答案 0 :(得分:1)
异常是不言自明的:除非根令牌是对象,否则无法将JSON转换为XML,即使您使用JsonConvertDeserializeXmlNode(String, String)
方法指定外部根元素名称也是如此。
至于为什么会这样,文档页面Converting between JSON and XML显示JSON数组转换为重复的XML元素序列而没有添加外部容器元素。即像这样的JSON(从文档中简化):
{
"root": {
"person": [
{
"name": "Alan"
},
{
"name": "Louis"
}
]
}
}
转换为XML,如下所示:
<root>
<person>
<name>Alan</name>
</person>
<person>
<name>Louis</name>
</person>
</root>
请注意,创建了一个外部<root>
节点,以及<person>
节点的重复序列 - 但两者之间没有任何内容?如果JSON中没有具有"root"
属性的外部对象,那么Json.NET将尝试使用多个<person>
根元素创建XML。 XML standard不允许这一点,它只需要一个根元素。因此,看起来JSON数组必须至少包含在两个级别的JSON对象嵌套中才能成功转换为XML(尽管其中一个级别可以通过{{1指定外部根元素名称来实现) }})。
作为解决方法,您可以引入以下扩展方法,将JSON嵌套在额外的对象级别中。
首先,通过How to string multiple TextReaders together?从Rex M的答案中抓取JsonConvertDeserializeXmlNode(String, String)
和ChainedTextReader
。使用它们,创建以下扩展方法:
public static TextReader Extensions.Concat(this TextReader first, TextReader second)
按如下方式转换为XML:
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();
}
}
}
}
使用您问题中的JSON,生成以下XML:
var doc = JsonExtensions.DeserializeXmlNode(data, "root", "array");
工作样本.Net fiddle。