Search code examples
c#json.netjson.netdeserialization

Netwonsoft JsonConvert.Deserialization Throws JsonSerializationException: 'Error converting value "My Custom Object's Name" to type 'System.Type'


I recently joined a new team at work and have been having some trouble setting up the repository for one of our applications, specifically I recieve an error when I try to perform an operation, and we haven't been able to reproduce this issue for any of the other team members.

For some additional context, the application is a windows app that runs on x64 architecture as a plugin for AutoCAD. We are a .NET shop, so the entire app was written in C# using .NET framework, although the framework versioning is not consistent across the repository.

The issue I'm experiencing is that the application has a generic function called CloneJson. For whatever reason, this method throws an exception when it tries to deserialize one of our custom objects, "PortMap". If you didn't catch it in the title, this deserialization is happening with the Newtonsoft.Json package.

Here is the full error: JsonSerializationException: 'Error converting value "CompanyName.ApplicationName.Common.Objects.Field.Reader, CompanyName.ApplicationName.Common.Objects, Version=1.0.8976.23506, Culture=neutral, PublicKeyToken=null" to type 'System.Type'.

Inner Exception: ArgumentException: Could not cast or convert from System.String to System.Type.

The error is thrown from the call to JsonConvert.Deserialize in the below method.

public static T CloneJson<T>(this T source)
{
 if ((object)source == null)
     return default(T);
 var settings = new Newtonsoft.Json.JsonSerializerSettings()
 {
     NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
     ObjectCreationHandling = Newtonsoft.Json.ObjectCreationHandling.Replace,
     TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto
 };
 var serializedObj = Newtonsoft.Json.JsonConvert.SerializeObject((object)source, settings);
 var deserializedOjb = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(serializedObj, settings);
 return deserializedOjb;
}

And this is the PortMap object. I can provide PanelPortRepExpanded as well, but as this is company code, I am trying to limit the amount I share to only what is absolutely necessary.

public class PortMap
{
    public List<PanelPortRepExpanded> Ports { get; set; } = new List<PanelPortRepExpanded>();
    public PortMap(List<PanelPortRepExpanded> ports)
    {
        Ports = ports;
    }
    public PortMap()
    {

    }
}

I've tried quite a few things at this point, including swapping the package versions, messing with the serialization settings. changing/checking the dependencies in various other ways, but I haven't had any luck.

I also tried resetting my laptop because I had a lot of random development environments, packages, etc installed that I was worried could be causing a conflict, but this didn't seem to have any effect.

Some other relevant details are:

  • As the issue is only reproducible on a PC that had not previously had the repository installed, its likely related to the changes the team made shortly before I joined.
  • One of these changes was related to the project dependencies, which resulted in missing dependencies in fresh repos when I first joined. we've since solved these issues by adding the missing DLLs that we were using to load various dependencies, but this could potentially be related to my issue still.

If you would like any additional details on the problem, please feel free to ask. I'm willing to try anything at this point, so any help is greatly appreciated!

Edit:

Here is the full ToString() output of the exception, as requested by dbc:

Newtonsoft.Json.JsonSerializationException: Error converting value "CompanyName.ApplicationName.Common.Objects.Field.Reader, CompanyName.ApplicationName.Common.Objects, Version=1.0.8976.25178, Culture=neutral, PublicKeyToken=null" to type 'System.Type'. Path 'Ports[0].PermittedTypes[0]', line 1, position 174. 
 ---> System.ArgumentException: Could not cast or convert from System.String to System.Type.
 at Newtonsoft.Json.Utilities.ConvertUtils.EnsureTypeAssignable(Object value, Type initialType, Type targetType)
 at Newtonsoft.Json.Utilities.ConvertUtils.ConvertOrCast(Object initialValue, CultureInfo culture, Type targetType)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
 --- End of inner exception stack trace ---
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
 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.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
 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.SetPropertyValue(JsonProperty property, JsonConverter propertyC onverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
 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.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
 at Newtonsoft.Json.Seri alization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
 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.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
 at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContain erContract 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 CompanyName.ApplicationName.Common.Objects.Helpers.Extensions.CloneJson[T](T source)

Here is the serialized Json as requested by DavidG. I took the liberty of truncating the data because each entry in the array was essentially identical data:

{
  "Ports": [
    {
      "PermittedTypes": [
        "CompanyName.ApplicationName.Common.Objects.Field.Reader, CompanyName.ApplicationName.Common.Objects, Version=1.0.8977.16740, Culture=neutral, PublicKeyToken=null"
      ],
      "PreferredTypes": [
        "CompanyName.ApplicationName.Common.Objects.Field.Reader, CompanyName.ApplicationName.Common.Objects, Version=1.0.8977.16740, Culture=neutral, PublicKeyToken=null"
      ],
      "AssociatedReaderSlot": 1,
      "ReservedFor": [],
      "PortName": "RDR 1",
      "DeviceId": "00000000-0000-0000-0000-000000000000"
    }
  ]
}

Solution

  • The issue turned out to be that AutoCAD has its own DLL for Newtonsoft.JSON, which was the same version as the one installed in the project via NuGet. Since our application is a plugin for AutoCAD, Visual Studio was loading the AutoCAD version instead of the Newtonsoft.JSON package installed in the project.

    Other coworkers had an older version of the Newtonsoft DLL in their AutoCAD program files, so I replaced the one in my AutoCAD folder with this one, and this fixed the issue.

    Thank you to anyone who took the time to try to help me solve this.