【问题标题】:Serializing an integer as hexadecimal in JSON.NET在 JSON.NET 中将整数序列化为十六进制
【发布时间】:2017-04-18 20:18:16
【问题描述】:

JSON.NET 支持deserializing hexadecimal numbers(例如0xffff),但是序列化怎么样?

以下工作,但似乎过于复杂:

public sealed class HexJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(uint).Equals(objectType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteRawValue($"0x{value:x}");
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override bool CanRead => false;
}

我正在寻找类似于DateFormatHandling 的东西,仅适用于整数。

【问题讨论】:

  • JsonTextWriter 相比,Newtonsoft.Json 的JsonTextReader 处理更多的幕后转换。 JSON 格式不支持十六进制,所以我会将值放在字符串中。否则你有什么工作。
  • 这是我知道的最简单的方法。其他选择是继承JsonTextWriter 并覆盖JsonTextWriter.WriteValue(Int32) 之类的方法。十六进制格式数字明显违反了JSON standard(与有no official JSON representation 的日期不同),这可能是未内置十六进制格式输出的原因。

标签: c# json json.net hex


【解决方案1】:

正如 cmets 中所指出的,JSON 中不允许使用十六进制文字(与 JavaScript 相反)。

转换器

uint 值转换为十六进制字符串文字,反之亦然:

public sealed class HexStringJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(uint).Equals(objectType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue($"0x{value:x}");
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var str = reader.ReadAsString();
        if (str == null || !str.StartsWith("0x"))
            throw new JsonSerializationException();
        return Convert.ToUInt32(str);
    }
}

使用示例

public sealed class CanonInfo
{
    [JsonConverter(typeof(HexStringJsonConverter))]
    public uint ModelId { get; set; }

    [JsonConverter(typeof(HexStringJsonConverter))]
    public uint FirmwareRevision { get; set; }
}

【讨论】:

  • 这段代码有一个错误。它应该是 Convert.ToUInt32(str, 16)。
  • @markf78 这段代码已经在生产环境中成功测试了好几年,查看github.com/CHDKUtil/CHIMP
  • 如果 str = "0x20",ReadJson 方法将抛出 FormatException。请参阅onlinegdb.com/Sk8dkCzqw 获取简单示例。
【解决方案2】:

下面的代码应该适用于您的HexJsonConverter 类中的序列化

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
     if(reader.ValueType.FullName == typeof(string).FullName)
    {
        string str = (string)reader.Value;
        if (str == null || !str.StartsWith("0x"))
            throw new JsonSerializationException();
        return Convert.ToUInt32(str.Substring("0x".Length), 16);
    }
    else
        throw new JsonSerializationException();
}

【讨论】:

    猜你喜欢
    • 2010-10-16
    • 2014-04-16
    • 2015-04-30
    • 2021-09-29
    • 1970-01-01
    • 2016-12-04
    相关资源
    最近更新 更多