I am generating a json object,
{
\"number\":0100
}
When this object is deserialized in C# using Newtonsoft.Json, 0100 i
I've looked at JsonTextReader.ParseNumber()
(the method where the "magic" of number reading happen). I'll say that it isn't doable. The octal case is especially handled
bool flag2 = c == '0' ...
and then
long value2 = text2.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ?
Convert.ToInt64(text2, 16) :
Convert.ToInt64(text2, 8); // Here OCTAL!!!
I haven't found any way to override this method (other than re-writing all the Read()
method that does everything in Json parsing)
If Newtonsoft.Json does that, then it is a bug. According to the JSON syntax as documented on http://json.org:
"A number is very much like a C or Java number, except that the octal and hexadecimal formats are not used."
and the syntax graph does not allow a number to have a leading non-significant zero.
RFC 4627 Section 2.4. agrees:
"Octal and hex forms are not allowed. Leading zeros are not allowed."
So in fact, your use of leading zeros is not valid JSON at all ... according to the RFC.
So, to answer your question:
Is there a way to override this functionality and make it consider the number as a decimal integer?
Probably not. Moreover, you shouldn't do it. Instead you should fix the JSON, or complain to the people who are generating it that it is not conformant.
You should also report this as a bug in Newtonsoft.Json.. Don't bother. The author does not acknowledge this as a bug. I would advise switching to a JSON library that implements the JSON spec correctly.
ADVICE FOR JSON IMPLEMENTERS
The JSON specs (both version) clearly say that hexadecimal and octal forms are not allowed.
If you add support for hex and/or octal (or some other unofficial "extension") to your JSON parser, you are adding to the fragmentation of the JSON standard. This is bad.
It is also a bad idea because many end-users are surprised when a non-significant leading zero is treated as an octal marker. This leads to Questions like this ... where (I'm guessing) the OP's end-users have been burned, and are requesting him to fix >>his<< code to handle leading zeros "properly".
The correct behavior here is to strictly implement the JSON spec, and reject any number with a non-significant leading zero. (Personally, I'd implement special-case error messages for this and for "0x..." hexadecimal forms.)
What is your .net framework?
You can use DataContractJsonSerializer object to deserialize that json.
I tried. It worked.
With .net 3.5: it's in System.ServiceMode.Web assembly.
With .net 4+: it's in System.Runtime.Serialization.Json assembly.
Example:
[DataContract]
public class TestObject
{
private int _id;
private string _name;
private decimal _number;
[DataMember]
public int ID
{
get
{
return _id;
}
set
{
_id = value;
}
}
[DataMember]
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
[DataMember]
public decimal Number
{
get
{
return _number;
}
set
{
_number = value;
}
}
}
Test
private string jsonText = "{\"Id\": 1, \"Name\": \"kanozuki\", \"Number\":\"0100\"}";
TestObject obj = Deserialise<TestObject>(jsonText);
public T Deserialise<T>(string json)
{
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(T));
using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
T result = (T)deserializer.ReadObject(stream);
return result;
}
}
Result
obj.Id:1
obj.Name:kanozuki
obj.Number:100