0

我正在使用 CodeFluent JsonUtilities 将对象转换为 JSON。使用其他任何东西似乎都有其他各种问题(例如循环引用)。

这是我使用 CodeFluent.Runtime.Utilities 命名空间(用于 JsonUtilities)转换为 ASP.NET MVC 的 JSON 的一些函数。

    public static ContentResult ConvertToJsonResponse(object obj)
    {
        string json = JsonUtilities.Serialize(obj);
        return PrepareJson(json);
    }

    /// <summary>
    /// Converts JSON string to a ContentResult object suitable as a response back to the client
    /// </summary>
    /// <param name="json"></param>
    /// <returns></returns>
    public static ContentResult PrepareJson(string json)
    {
        ContentResult content = new ContentResult();
        content.Content = json;
        content.ContentType = "application/json";

        return content;
    }

问题是当我使用 JsonUtilities 转换对象时,它似乎跳过了一些嵌套对象。

例如,我尝试使用 CodeFluent 将 DataSourceResult 对象(来自 Telerik)转换为 JSON。

public ActionResult UpdateTeam([DataSourceRequest]DataSourceRequest request, TeamViewModel teamViewModel)
{
    ModelState.AddModelError("", "An Error!");
    DataSourceResult dataSourceResult = new[] { teamViewModel }.ToDataSourceResult(request, ModelState);
    ContentResult ret = CodeFluentJson.ConvertToJsonResponse(dataSourceResult);
    return ret;
}

dataSourceResult 包含三个主要属性:

  1. 数据 - 包含我的模型,其中包含我的数据。
  2. Total - 包含数据对象的数量。
  3. 错误 - 包含我的 MVC 模型的所有错误。它非常嵌套,下面有很多属性。

当我尝试使用 CodeFluent 实用程序转换 DataSourceResult 对象时,它可以转换“Data”和“Total”字段,但如果出现错误,它会完全跳过它,从而产生以下 JSON 字符串:

{  
   "Data":[  
      {  
         "ExampleProperty":"ExampleValue"
      }
   ],
   "Total":1,
   "AggregateResults":null,
   "Errors":{  }
}

我猜问题出在“错误”对象对于 CodeFluent 转换器来说过于嵌套。所以我的问题是我是否缺少任何 CodeFluent 序列化选项/代码来处理大量嵌套的对象以进行 JSON 转换?

4

1 回答 1

1

问题来自您使用空键创建模型错误的事实。这不是被禁止的,但 JsonUtilities 只是根据设计跳过带有空键的字典值。

只需使用真正的密钥,如下所示:

ModelState.AddModelError("my first error", "An Error!");
ModelState.AddModelError("my second error", "An Error!");

您会看到错误集合已序列化,如下所示:

{
 "Data":[  
  {  
     "ExampleProperty":"ExampleValue"
  }],
 "Total": 1,
 "AggregateResults": null,
 "Errors": {
   "my first error": {
     "errors": [
       "An Error!"
      ]
    },
   "my second error": {
     "errors": [
       "An Error!"
      ]
    }
  }
}

否则,如果您真的想保留空键,那么您可以利用JsonUtilitiesOptions具有回调的类来调整序列化(和反序列化)过程。小心这一点,因为您可以轻松破坏 JSON 语法。这就是你可以这样做的方式,应该可以处理所有情况:

JsonUtilitiesOptions options = new JsonUtilitiesOptions();
options.WriteValueCallback += (e) =>
{
    IDictionary valueDic = e.Value as IDictionary;
    if (valueDic != null)
    {
        e.Writer.Write('{');
        bool first = true;
        foreach (DictionaryEntry entry in valueDic)
        {
            if (!first)
            {
                e.Writer.Write(',');
            }
            else
            {
                first = false;
            }

            // reuse JsonUtilities already written functions
            JsonUtilities.WriteString(e.Writer, entry.Key.ToString(), e.Options);
            e.Writer.Write(':');
            // object graph is for cyclic/infinite serialization checks
            JsonUtilities.WriteValue(e.Writer, entry.Value, e.ObjectGraph, e.Options);
        }
        e.Writer.Write('}');
        e.Handled = true; // ok, we did it
    }
};
string json = JsonUtilities.Serialize(obj, options);

现在,您将得到以下结果:

{
 "Data":[  
  {  
     "ExampleProperty":"ExampleValue"
  }],
 "Total": 1,
 "AggregateResults": null,
 "Errors": {
   "": {
     "errors": [
       "An Error!"
      ]
    }
  }
}
于 2015-11-29T11:45:20.110 回答