【问题标题】:JSON.NET serializer improperly serializes string as booleanJSON.NET 序列化程序错误地将字符串序列化为布尔值
【发布时间】:2017-02-20 21:00:35
【问题描述】:

我有一堂课:

[JsonObject(MemberSerialization.OptIn)]
public class UserPreferenceDTO
{
    [JsonProperty]
    public string Name { get; set; }

    [JsonProperty]
    public string Value { get; set; }

    public static explicit operator UserPreferenceDTO(UserPreference pref)
    {
        if (pref == null) return null;
        return new UserPreferenceDTO
        {
            Name = pref.Name,
            Value = pref.Value
        };
    }

    public static explicit operator UserPreference(UserPreferenceDTO pref)
    {
        if (pref == null) return null;
        return new UserPreference
        {
            Name = pref.Name,
            Value = pref.Value
        };
    }
}

还有一个控制器,例如:

public HttpResponseMessage Post(int caseid, Guid id, UserPreferenceDTO prefs)
{ ... }

注意:控制器类装饰有[CamelCaseControllerConfig] 属性 这是做什么的:

public void Initialize(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
{
   var formatter = controllerSettings.Formatters.OfType<JsonMediaTypeFormatter>().Single();
   controllerSettings.Formatters.Remove(formatter);

   formatter = new JsonMediaTypeFormatter
   {
       SerializerSettings = { ContractResolver = new CamelCasePropertyNamesContractResolver() }
   };

   controllerSettings.Formatters.Add(formatter);

}

在客户端我通过这样的对象发送:

{ name: "name", value: "Some value" }

value 通常是一个 JS 布尔值。问题是当它到达控制器时,布尔值被转换为 C# 布尔值 (True/False) 并被字符串化。

例如发送

'{ "name": "wantColFit", "value": "false" }'

变成:

在 .NET 控制器中。

如果您查看模型 (UserPreferenceDTO) 定义,Value 采用 string。那么为什么序列化器将值转换为布尔值呢?

我更希望在保存时将值保留为"true"/"false"(这将更容易在客户端解析回布尔值,因为JSON.parse("true") === trueJSON.parse("True") !== true

【问题讨论】:

  • 这有点令人困惑。你说要发送{ name: "name", value: "value" } 之类的东西,但你说你要发送{ "wantColFit": "false" }。你实际上是发送那个还是{ "name": "wantColFit", "value": false }?我希望后者会导致您所看到的。我不确定 .NET 如何将 { "wantColFit": "false" } 解析为具有 Name 和 Value 属性的对象...
  • @MikeMcCaughan 你完全正确。已编辑。

标签: c# asp.net asp.net-web-api json.net


【解决方案1】:

Json Boolean 将被映射到 C# bool。 由于您的字段名称相同,并且在 C# 端它是字符串,因此 bool 已转换为字符串。 根据 .NET 的中间语言布尔值“true”将在 .Net 中变为“True”。

要解决此问题,您需要使用引号传递布尔值,或者需要更改您的 C# 属性。

string valueField = "";

[JsonProperty]
public string Value 
{ 
   get{
       return valueField.ToLower();
    }
   set{
      value = valueField;
   }
}

【讨论】:

  • 值可以是任何东西。就像一个字符串化的对象/数组等。所以我无法将 getter 更改为您建议的内容
  • 返回值字段=="True" || valueField=="False" ?valueField.ToLower():valueField;
【解决方案2】:

无法弄清楚 Json.Net 如何(以及为什么)将像 "true" 这样的字符串反序列化为 C# 布尔值 True,所以我只是借用了这个要点:BooleanConverter.js 其中ReadJson 是这样做的:

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var val = reader.Value.ToString().ToLower().Trim();

        if (val == "true" || val == "false")
            return val;

        // If we reach here, we're pretty much going to throw an error so let's let Json.NET throw it's pretty-fied error message.
        return new JsonSerializer().Deserialize(reader, objectType);
    }

并且我能够将我的模型序列化为正确的 "true""false" 值(而不是 "True""False"

如果有人可以回答 Json.Net 在内部做什么来转换类似布尔值的字符串 "true"/"false",我会接受他们的回答。

【讨论】:

    猜你喜欢
    • 2014-08-06
    • 2020-05-20
    • 2017-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-24
    相关资源
    最近更新 更多