There are two things that come into play here:
The only actually invalid part of that JSON are its quotation marks. JSON actually only allows strings enquoted by double quotation marks, so it’s maybe a bit odd that the JavaScriptSerializer supports deserializing single quotation marks.
This is a deliberate choice to support multiple alternative formats. The underlying deserializer actually even supports leaving out the quotation marks for property names, so the following would be valid too (which makes sense given that it’s also a valid JavaScript expression):
{ firstName: 'John', lastName: 'Doe', id: 10. }
The other part which you mentioned is that 10. number which is not an integer but is deserialized just fine as an integer. This is because JSON—like JavaScript—only knows about numbers. There is no difference between integers and non-integers; there is only a single number type which is an IEEE-754 floating point number, like .NET’s double.
So when deserializing, the base type cannot be taken into account since that would always be a double. But the underlying deserializer actually does attempt to get some information from the actual string representation. So a value of 10 would return an integer, while a value of 10. would return a decimal.
However, when that information is then used and applied to the target type that restriction is loosened, and a converter is used to convert the decimal into the int—since the decimal 10.0 would fit in an int.
JavaScriptSerializerknowingly accepts that and still parses it when it can.10.is the same as10. So the deserializer only sees the “number” (actually it’s always like a double), and checks whether it could write it into the targetintproperty. If that works (because the double happens to be an integer), then that’s fine.