5

I have this array:

{
    "AssemblyVersion":"0.1.333.5973",
    "Exception":
    {
        // [...]
    }
}

which is serialized from this class:

public class ErrorData
{
    public string AssemblyVersion { get; private set; }
    public Exception Exception { get; private set; }

    public ErrorData(string assemblyVersion, Exception ex)
    {
        AssemblyVersion = assemblyVersion;
        Exception = ex;
    }

    public override string ToString()
    {
        return JsonConvert.SerializeObject(this);
    }
}

Serializing it back to an object produces the following exception:

Newtonsoft.Json.JsonReaderException: Input string '0.1.335.5973' is not a valid number. Path 'AssemblyVersion', line 1, position 29.
    at Newtonsoft.Json.JsonTextReader.ParseNumber(ReadType readType)
    at Newtonsoft.Json.JsonTextReader.ReadStringValue(ReadType readType)
    at Newtonsoft.Json.JsonTextReader.ReadAsString()
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, JsonContract contract, Boolean hasConverter)
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType)
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id)
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator)
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
    at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
    at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
    at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
    at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value)

In a nutshell I'm serializing an ErrorData instance as a json string with the overridden ToString() method, passing the result as a command line argument to a child process which is deserializing it back to an ErrorData instance.

What am I missing? It seems like the AssemblyVersion string is seen as a number instead of a string.

Edit:

I'm deserializing it this way:

ErrorData errorData = JsonConvert.DeserializeObject<ErrorData>(args[0]);

Serializing is already shown in the code above, I implemented it into ToString() method.

I can verify that it happens because I'm passing the array as a command line arg. This code here works:

ErrorData errorData = Json.DeserializeObject<ErrorData>(new ErrorData("", new Exception()).ToString());
Christian Klemm
  • 1,455
  • 5
  • 28
  • 49
  • 2
    Can you show the code you're using for the serialization and deserialization? – Doug Wilson May 08 '16 at 17:49
  • What is the full `ToString()` output of the exception including the exception type, message, **traceback inside Json.NET** and InnerException, if any? – dbc May 08 '16 at 17:55
  • @dbc The ToString() method is not throwing the exception. It is thrown when deserialized back into an object. However I added the full exception – Christian Klemm May 08 '16 at 18:00
  • @dbc like I already said: ToString() is not throwing any exception. Dezerializing the json string throws the exception – Christian Klemm May 08 '16 at 18:08
  • I can't reproduce this -- see https://dotnetfiddle.net/H68FeX. The only problem I found is that I needed to change the *names of the constructor parameters* to `public ErrorData(string assemblyVersion, Exception exception)`. For an explanation of why, see [Avoiding default constructors and public property setters](https://stackoverflow.com/questions/35245256/avoiding-default-constructors-and-public-property-setters/35247524#35247524). What version of Json.NET are you using? – dbc May 08 '16 at 18:29
  • You're right, I was missing that. How did you tried to reproduce this? Did you passed the JSON string as a parameter to a second assembly? – Christian Klemm May 08 '16 at 18:42
  • I did what was shown in the [fiddle](https://dotnetfiddle.net/H68FeX), though when running locally in Visual Studio it was not necessary to set `IgnoreSerializableInterface = true`. Can you show the specific JSON that throws the exception? – dbc May 08 '16 at 18:59
  • 1
    I think this problem just occurs because I'm passing this JSON array as a command line parameter to a child process – Christian Klemm May 08 '16 at 19:15
  • 1
    That's probably it then. You didn't escape the \" character around the `0.1.335.5973` so Command Prompt ate it somehow, leading Json.NET to try to parse it as a numeric token. See http://superuser.com/questions/206436/how-do-i-escape-the-string-for-command-line-in-windows. – dbc May 08 '16 at 19:43
  • Maybe see http://stackoverflow.com/questions/5510343/escape-command-line-arguments-in-c-sharp – dbc May 08 '16 at 19:45
  • 2
    I think I will write the data as a file into temp folder and just pass the path to the file to the child process. Should be the easiest way – Christian Klemm May 08 '16 at 19:46
  • Or pass it through standard input. http://stackoverflow.com/questions/19720288/c-sharp-process-call-interact-with-standard-input-and-standard-output – dbc May 08 '16 at 19:49
  • Or this way. Thanks for the help – Christian Klemm May 08 '16 at 19:50

1 Answers1

-1

I suggest that you should check your input, because following code will throw exception about invalid number:

JsonConvert.DeserializeObject<ErrorData>("{'AssemblyVersion':0.1.333.5973,'Exception':{}}");

But if you quote AssemblyVersion value, then deserialization will succeed:

JsonConvert.DeserializeObject<ErrorData>("{'AssemblyVersion':'0.1.333.5973','Exception':{}}");
tekado
  • 123
  • 6