C# 通过web api使无模式json可序列化

C# 通过web api使无模式json可序列化,c#,asp.net-web-api,json.net,deserialization,content-negotiation,C#,Asp.net Web Api,Json.net,Deserialization,Content Negotiation,我有一个JSON字符串,其中包含一个复杂的嵌套对象,并且将来可能会更改模式。我想把它交给一个web API,以便根据需要在内容协商管道中序列化 有什么简单的方法可以做到这一点吗?我已经阅读了关于这个问题的其他答案,但它们只讨论了您事先知道所需模式的情况(例如使用JsonConvert.DeserializeAnonymousType反序列化)或您知道要反序列化的嵌套深度的情况 例如,假设我有以下字符串: @"{ name: "Dan" children: [

我有一个JSON字符串,其中包含一个复杂的嵌套对象,并且将来可能会更改模式。我想把它交给一个web API,以便根据需要在内容协商管道中序列化

有什么简单的方法可以做到这一点吗?我已经阅读了关于这个问题的其他答案,但它们只讨论了您事先知道所需模式的情况(例如使用
JsonConvert.DeserializeAnonymousType
反序列化)或您知道要反序列化的嵌套深度的情况

例如,假设我有以下字符串:

    @"{
      name: "Dan"
      children: [
         {
            name: 'Fred',
         },
         {
            name: 'Fannie',
            age: 30,
            children: {
                own: [
                    {name: "Barney"},
                    {name: "Angela"}
                ],
                adopted: {
                    {name: "Sven"}
                }            
            }  
        }
    }"
我不知道它的模式是什么,它可以随时更改,我只希望能够通过web api通过适当的内容协商发送它


我可以做
JObject.Parse(…)
但web api不能正确处理
JObject
s。它可以正确处理字典,但我似乎不知道如何使用JSON.Net对任意嵌套深度的字典进行反序列化。

我通过将动态对象转换为
列表
实现了这一点。请澄清这是否是您需要的

好的,在你更新了你的问题之后,很明显你甚至不需要将它序列化到字典中。只需使用(它内置于WebApi中,并被用作默认JSON序列化程序btw)

另外,请确保将来您通过考试

工作示例(WebApi2) JSON负载

{
    "name": "Dan",
    "children": [
        {
            "name": "Fred"
        },
        {
            "name": "Fannie",
            "age": 30,
            "children": {
                "own": [
                    {
                        "name": "Barney"
                    },
                    {
                        "name": "Angela"
                    }
                ],
                "adopted": [
                    {
                        "name": "Sven"
                    }
                ]
            }
        }
    ]
}
代码

回应

作为他们的客户,Json.NET可以直接从Json转换为XML。以下是他们文档中的示例:

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);
// <?xml version="1.0" standalone="no"?>
// <root>
//   <person id="1">
//   <name>Alan</name>
//   <url>http://www.google.com</url>
//   </person>
//   <person id="2">
//   <name>Louis</name>
//   <url>http://www.yahoo.com</url>
//   </person>
// </root>
stringjson=@”{
“?xml”:{
“@version”:“1.0”,
“@standalone”:“否”
},
“根”:{
“人”:[
{
“@id”:“1”,
“姓名”:“艾伦”,
“url”:”http://www.google.com'
},
{
“@id”:“2”,
“姓名”:“路易斯”,
“url”:”http://www.yahoo.com'
}
]
}
}";
XmlDocument doc=(XmlDocument)JsonConvert.DeserializeXmlNode(json);
// 
// 
//   
//艾伦
//   http://www.google.com
//   
//   
//路易
//   http://www.yahoo.com
//   
// 

因此,要么将JSON作为字符串传递(未经修改),要么根据请求的内容类型转换为XML。

因此,经过长时间的调查,我设法将问题归结为:

  • 当指定xml的内容类型时,默认情况下Web Api使用(现在基本上放弃了)
    XmlSerializer
  • XmlSerializer
    无法序列化
    JObject
    s
  • 没有内置的方法将任意嵌套深度的
    JObject
    s转换为字典(尽管使用自定义递归函数来实现这一点并不十分困难)
因此,解决这个问题的方法是实现您自己的xml格式化程序,它可以转换为字典或使用类似的工具。这听起来很简单,但我无法启动自定义格式化程序



最后,我简单地删除了xml格式化程序,因为它对于我的api来说并不是绝对必要的,而且比它的价值更麻烦。

你刚才说要将JSON字符串序列化为JSON吗?你可以始终使用
JObject.Parse(JSON)
返回解析后的JObject(它还实现了IDictonary).但我不明白您想如何在不知道任何信息的情况下从中获取属性。@L.B.我想使用web api将其发送到客户端。Web Api可以将其序列化为xml或json或其他形式,具体取决于可用的处理程序。然而,它不能从
JObject
@georgemauer-OK转换成xml,但是你的问题是“我有一个JSON字符串……我想把它交给web API序列化为xml或JSON”。不管怎样,你甚至会如何处理这样的对象?如果不知道它的模式,就不知道它的属性。你只是完全通过反射与它进行交互吗?@GeorgeMauer那么为什么不将JSON转换成一个对象,然后根据需要将该对象序列化为JSON到XML呢?我认为你把所有人都弄糊涂了,因为你没有简明扼要地描述这个问题。是的,但这如何与web api内容协商相适应呢?@GeorgeMauer当然会有所帮助<代码>内容协商不是魔术。您将从请求中读取
Accept
标题,然后相应地序列化内容(xml或json)(顺便说一句:我已经用WCF手动完成了很多次)@L.B是的,我可以手动完成各种事情-如果我想,我甚至可以编写一个超级手动完成事情的OWIN组件。但我正试图以WebApi特有的方式来实现它,我不知道这将如何融入到这个方案中。@GeorgeMauer您必须编写它:)@GeorgeMauer我知道您的期望,但不认为您会以您期望的方式实现它。@GeorgeMauer检查答案如果您发送一个包含
application/xml
to your Test method?@BrianRogers默认情况下,WebApi无法反序列化未定义为xml的对象。无论如何,您可以删除默认的XML序列化程序并添加自己的序列化程序。这只是重申了我提到的WebApi可以将
JObject
序列化为json而不是xml的问题。令人沮丧的是,匿名类型或字典可以序列化。所以诀窍是将
JObject
转换为其中之一。
JsonConvert.DeserializeObject(json)
不能处理任意嵌套深度字典吗?我听说可以,但我自己还没试过。我可能被误导了。@Nick
DeserializeObject
可能能够处理它,但这是专门针对另一个方向的——序列化。您说过“没有内置的方法将任意嵌套深度的作业对象转换为字典(尽管要实现这一点,自定义递归函数并不十分困难)。”这就是反序列化。@尼克:不,反序列化是从字符串(或字节等其他平面格式)到结构化对象。Ser
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);
// <?xml version="1.0" standalone="no"?>
// <root>
//   <person id="1">
//   <name>Alan</name>
//   <url>http://www.google.com</url>
//   </person>
//   <person id="2">
//   <name>Louis</name>
//   <url>http://www.yahoo.com</url>
//   </person>
// </root>