【问题标题】:Object of type 'Newtonsoft.Json.Linq.JObject' cannot be converted to type'Newtonsoft.Json.Linq.JObject' 类型的对象无法转换为类型
【发布时间】:2015-04-01 20:03:13
【问题描述】:

我正在使用 JSON.NET 通过反射将一些数据解析为一些特定的属性。

property.SetValue(comInstance, field.Value);

这一行会抛出一个ArgumentException

在 mscorlib.dll 中发生了“System.ArgumentException”类型的未处理异常

附加信息:“Newtonsoft.Json.Linq.JObject”类型的对象无法转换为“Microsoft.Xna.Framework.Vector2”类型。

我知道这一定与我的JsonConverterVector2 类型有关,看起来像这样:

public class Vector2Converter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Vector2));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jsonObject = JObject.Load(reader);
        var properties = jsonObject.Properties().ToList();
        return new Vector2
        {
            X = (float)properties[0].Value,
            Y = (float)properties[1].Value
        };
    }
    
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Vector2 v = (Vector2)value;
        writer.WriteStartObject();
        writer.WritePropertyName("X");
        serializer.Serialize(writer, v.X);
        writer.WritePropertyName("Y");
        serializer.Serialize(writer, v.Y);
        writer.WriteEndObject();
        
    }
}

现在,我注意到 write 被调用,但 read 从来没有。 我这样反序列化:

JsonConvert.DeserializeObject<EntityJson>(json, JsonUtility.Settings);

JsonUility.Settings 包含Vector2Converter

我这样序列化:

JsonConvert.SerializeObject(entityJson, Formatting.Indented, JsonUtility.Settings);

JSON 本身的字段看起来也不错:

"Center": {
      "X": 116.0,
      "Y": 65.0
    },

谁能帮帮我?

编辑:

internal class EntityJson
{
    public string Name { get; set; }
    public Dictionary<string, ComponentJson> Components { get; set; }
    
    public EntityJson()
    {
        Components = new Dictionary<string, ComponentJson>();
    }

    public Entity ToEntity()
    {
        Entity entity = new Entity(Name);

        foreach(KeyValuePair<string, ComponentJson> com in Components)
        {
            ObjectHandle handle = Activator.CreateInstance(com.Value.Namespace, com.Value.Namespace +"."+ com.Key);
            Object handleValue = handle.Unwrap();
            Component comInstance = (Component)handleValue;

            foreach(KeyValuePair<string, object> field in com.Value.Fields)
            {
                PropertyInfo property = comInstance.GetType().GetProperty(field.Key, 
                    BindingFlags.NonPublic | 
                    BindingFlags.Public | 
                    BindingFlags.Instance);

                property.SetValue(comInstance, field.Value); // <-- field.Value
            }

            entity.AddUnsafe(comInstance);
        }

        return entity;
    }
}

field.value 将是 JObject 而不是 Vector2,异常状态:

它不能被铸造。

【问题讨论】:

  • JSON 转换器是否抛出异常?我在转换器的任何地方都没有看到代码行 property.SetValue(comInstance, field.Value);
  • 您的EntityJson 班级是什么样的?该类中 Vector2 的属性名称是否与您要反序列化的 JSON 中的属性名称匹配?
  • 您需要向我们展示调用property.SetValue(comInstance, field.Value); 的代码。但是如果field.ValueJObject,并且您在某个更高级别的JSON 转换器中,则需要将其转换为目标类型,例如JToken.ToObject Method (Type, JsonSerializer)
  • 这是我的 EntityJson 的样子:

标签: c# json xna json.net


【解决方案1】:

好的,我设法解决了这个问题:

object result = field.Value;
if (field.Value.GetType() == typeof(JObject))
{
      JToken token = (JToken)field.Value;
      result = token.ToObject(property.PropertyType, JsonSerializer.Create(JsonUtility.Settings));
}
else
{
      result = Convert.ChangeType(result, property.PropertyType);
}

property.SetValue(comInstance, result); 

这是一个稳定的解决方案吗?

【讨论】:

  • 如果您尝试将 JSON 片段应用于预先存在的对象,您可以使用 JsonConvert.PopulateObject 并让 Json.NET 为您进行反射。
  • “这是一个稳定的解决方案吗?” - 这可以说是一个新的 问题
  • @MickyDuncan:听起来比 SO 更接近 Code Review
  • @NathanTuggy Thx Nathan,不知道那个子站点
  • 哦,对不起,如果我没记错的话,我可能在这里问的第一个问题。我会记住的,谢谢。
猜你喜欢
  • 1970-01-01
  • 2014-07-09
  • 1970-01-01
  • 2022-12-07
  • 2020-03-17
  • 2016-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多