如何使用WebAPI返回Dictionary<complexType,int>?

9

我提供的是一个WebApi 2端点,其实现方式如下:

我的控制器很简单:

 public IDictionary<MyClass, int> GetMyClasses(string id)
 {
    Dictionary<MyClasses, int> sample = new Dictionary<MyClasses, int>();

    sample.Add(new MyClasses()
    {
       Property1 = "aaa",
       Property2 = 5,
       Property3 = 8
    },10);

    return sample;
 }

MyClass的结构如下:

public class MyClass
{
   string Property1 {get;set;}
   int Property2 {get;set;}
   int Property3 {get;set;}
}

当我运行我的 Web 服务时,辅助网页显示我期望的输出为:
{ "MyNamespace.MyProject.MyClass": 1 }

另一方面,XML示例是我想要的(除了我需要JSON而不是XML):
<ArrayOfKeyValueOfMyClassintl85fHlC_P xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
  <KeyValueOfMyClassintl85fHlC_P>
    <Key xmlns:d3p1="http://schemas.datacontract.org/2004/07/MyNamespace.MyProject.MyClass">
      <d3p1:Property1>sample string 4</d3p1:Property1>
      <d3p1:Property2>8</d3p1:Property2>
      <d3p1:Property3>5</d3p1:Property3>
    </Key>
    <Value>1</Value>
  </KeyValueOfMyClassintl85fHlC_P>
</ArrayOfKeyValueOfMyClassintl85fHlC_P >

我还使用Postman运行了终端节点,确认返回的值与WebApi默认页面预览的值一致。

为什么json是“错误的”,而xml做得很好(我的意思是包含所有数据)?

更新:

我希望MyClass序列化成json格式如下:

{
  "Property1": "sample string 4",
  "Property2": 8,
  "Property3": 5
}

这应该是我的字典键的结构,就像它在xml表示中一样。
谢谢

你会期望这个产生什么样的JSON? - StriplingWarrior
你已经澄清了你期望如何序列化MyClass,但是你希望一个IDictionary<MyClass,int>被序列化成什么样子? - StriplingWarrior
@StriplingWarrior,我写的序列化程序中使用了"MyNamespace.MyProject.MyClass",你认为这会_损坏_JSON吗? - ff8mania
1
WebApi 2 使用Json.NET作为其JSON格式化程序。默认情况下,Json.NET 只能序列化键可以转换为字符串的字典。请参见此处的解决方法:https://dev59.com/OYXca4cB1Zd3GeqPN9ON - dbc
@ff8mania:我希望你能澄清一下你想要的返回值是什么样子,这样我就可以提供你想要的答案,而不是三个单独的答案和解释每种情况下应该使用哪个。如果你花点时间写出你所设想的整个JSON对象,你就可以节省我很多时间。 - StriplingWarrior
4个回答

7

这种方法有点hacky,但是在将Dictionary对象转换成List对象之后再通过JsonConvert进行操作,我成功了。看看下面的代码:

IDictionary<MyClass,int> dict = new Dictionary<MyClass, int>();
MyClass classy = new MyClass() { value = value };
dict.Add(classy, 5);
string json = JsonConvert.SerializeObject(dict); //<--- Returns [{MyClass: 5}], boo

Whereas . . .

string json = JsonConvert.SerializeObject(dict.ToList()); //<--- Returns [{Key: blah blah blah, Value: 5}], nice

希望这能帮到你。

4

你的控制器长什么样子?端点应该长成这个样子:

[Route("")] 
public IHttpActionResult Get() 
{ 
    IDictionary<MyClass, int> resource = new Dictionary<MyClass, int> 
    {
        { new MyClass {Property1="1", Property2=2, Property3=3}, 0 },
        { new MyClass {Property1="11", Property2=22, Property3=33}, 1 },
    };

    return Ok(resource); 
} 

如果您在处理JSON序列化问题时仍有困难,您可以在Web API中配置默认的JsonFormatter类型:GlobalConfiguration.Configuration.Formatters.JsonFormatter;。有关更多信息,请参阅ASP.NET Web API序列化文档

3
通常字典用于通过在JavaScript对象上使用键/值对作为名称/值对来生成更动态的JSON对象。但是,JSON对象不能将另一个JSON对象用作其键。例如,以下语法无效:
{
    {"Property1": "sample string 4",... } : 1,
    {"Property1": "sample string 5",... } : 2,
}

因此,您需要决定如何在JSON中表示这些信息。您是否将其视为键/值对象的数组?

[ 
    { Key: {"Property1": "sample string 4",...}, Value: 1 },
    { Key: {"Property1": "sample string 5",...}, Value: 2 },
]

在这种情况下,从你的方法中返回一个List<KeyValuePair<string, int>>,使用dict.ToList()
你的键和值是否有意义?也许你应该创建一个类来表示每个项目,具有自定义属性名称,使用dict.Select(kvp => new MyDto { MyClass = kvp.Key, Foo = kvp.Value }).ToList()
[ 
    { MyClass: {"Property1": "sample string 4",...}, Foo: 1 },
    { MyClass: {"Property1": "sample string 5",...}, Foo: 2 },
]

您希望继续使用对象,但左侧为类的字符串表示形式?您可以通过在MyClass上实现ToString()方法来实现此目的:

{ 
    "sample string 4|8|5": 1, 
    "sample string 5|6|7": 2
} 

0

我没时间解释。 只需看例子。

[HttpGet("CountUserTasksNumberInProject/{userId}")]
public ActionResult<ICollection<KeyValuePair<ProjectDTO, int>>> 
ReadCountUserTasksNumberInProject(int userId)
{
    Dictionary<ProjectDTO, int> result = _service.CountUserTasksNumberInProject(userId);

    if (result == null)
    {
        return NotFound();
    }
    else
    {                
        return Ok(result);
    }
}   

[
  {
    "key": {
      "id": 0,
      "authorId": 0,
      "teamId": 0,
      "name": "string",
      "description": "string",
      "deadline": "2022-07-14T10:17:12.260Z",
      "createdAt": "2022-07-14T10:17:12.260Z"
    },
    "value": 0
  }
]   

2
最好解释一下你的代码。 - Mahyar Mottaghi Zadeh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接