5

JSON.NET supports deserializing hexadecimal numbers (e.g. 0xffff), but how about serializing?

The following works, but seems far too complicated:

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;
}

I am looking for something along the lines of DateFormatHandling, only for integers.

2
  • 1
    The JsonTextReader for Newtonsoft.Json handles many more behind-the-scenes conversions compared to the JsonTextWriter. The JSON format doesn't support hexadecimal, so I would put the value inside a string. What you have works otherwise. Commented Apr 18, 2017 at 20:44
  • 3
    That's the easiest way I know. Other option would be to subclass JsonTextWriter and override methods like JsonTextWriter.WriteValue(Int32). Hex format numbers explicitly violate the JSON standard (unlike dates for which there is no official JSON representation) which may be why hex format output is not built-in. Commented Apr 18, 2017 at 20:50

2 Answers 2

10

As pointed out in the comments, hexadecimal literals are not allowed in JSON (contrary to JavaScript).

Converter

Converts uint values to hexadecimal string literals and vice versa:

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);
    }
}

Usage example

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

    [JsonConverter(typeof(HexStringJsonConverter))]
    public uint FirmwareRevision { get; set; }
}
Sign up to request clarification or add additional context in comments.

3 Comments

This code has a bug in it. It should be Convert.ToUInt32(str, 16).
@markf78 This code has been successfully tested in production for quite a few years, check out github.com/CHDKUtil/CHIMP
The ReadJson method will throw a FormatException if str = "0x20". Please see onlinegdb.com/Sk8dkCzqw for a simple example.
2

The below code should work for serialization in your HexJsonConverter class

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();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.