【问题标题】:CodeFluent JSON Serialization Does Not Work for All FieldsCodeFluent JSON 序列化不适用于所有字段
【发布时间】:2015-12-02 14:59:23
【问题描述】:

我正在使用 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. Data - 包含我的模型,其中包含我的数据。
  2. Total - 包含数据对象的数量。
  3. Errors - 包含我的 MVC 模型的所有错误。它非常嵌套,下面有很多属性。

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

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

我猜测问题在于“错误”对象对于 CodeFluent 转换器而言嵌套过多。 所以我的问题是我是否缺少任何 CodeFluent 序列化选项/代码来处理 JSON 转换的重度嵌套对象?

【问题讨论】:

  • 你能详细说明 DataSourceResult 是什么类吗?来自什么 Telerik 产品?
  • 查看此链接:doylestowncoder.wordpress.com/2014/04/14/… Telerik DataSourceResult 对象来自 Telerik ASP.NET MVC。它是一个默认类,用于格式化我的响应以发送到 Telerk ASP.NET MVC Grid(可能还有其他使用 DataSource 对象的控件)。对于我的 MVC 网格上的读取操作,它会执行我所有的分页、排序、过滤和格式化我的模型对象和模型状态错误,以将其发送回 MVC 网格,以便它处理 CRUD 操作。对于创建/更新/删除,据我所知,它主要用于错误处理目的。

标签: json model-view-controller telerik codefluent


【解决方案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!"
      ]
    }
  }
}

【讨论】:

  • 这可行,但是是否有任何序列化程序选项可以设置为不跳过带有空键的字典值?还是没有提供这个选项?不放置存根键会很有用,因为采用此 JSON 对象的 JavaScript 在“错误”中使用这些键来指示哪些字段有错误。就我而言,这是一个自定义错误,并非特定于某个字段。
  • 您可以使用选项来实现(定义一个 JsonUtilitiesOptions 并在其上定义回调),但它还需要一些额外的代码。但是你是对的,空字符串在 json 中作为字典键似乎是合法的(虽然有点奇怪)。我们将更改序列化程序,使其不会跳过空(非空)字典键。请注意,与其他键一样,给定字典中只能有一个空键。
  • “您可以使用选项来实现(定义一个 JsonUtilitiesOptions 并在其上定义回调)”。我熟悉使用 JsonUtilitiesOptions 设置序列化选项,如何在其上定义回调以获得我正在寻找的效果?
  • @Oniisaki - 最新(昨天)版本包括处理空键和非空键。
  • 非常感谢。我尝试了更新后的代码,现在它可以完美地与空键一起使用。
猜你喜欢
  • 1970-01-01
  • 2019-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多