【问题标题】:Populate object with non-primitive property as String from JSON将具有非原始属性的对象填充为 JSON 中的字符串
【发布时间】:2017-09-15 09:01:58
【问题描述】:

我有以下两个示例类。首先是用户类...

public class User : ILoadable
{
    public User(string code)
    {
        this.Load(code);
    }

    public string Code { get; set; }

    public UserGroup Group { get; set; }
}

... 和 UserGroup 类。

public class UserGroup : ILoadable
{
    public UserGroup(string code)
    {
        this.Load(code);
    }

    public string Code { get; set; }

    public int GroupId { get; set; }

    // More properties
}

然后我有一个方法用构造函数调用的 json 文件中的数据填充对象:

public static void Load(this ILoadable obj, string code)
{
    string json = GetJsonFromCode(obj.GetType(), code);
    JsonConvert.PopulateObject(json, obj);
}

我想要的不是保存 User 及其完整的 UserGroup 属性数据,而只是保存其代码,因此可以通过将代码传递给 UserGroup 构造函数并从那里获取整个对象来重建它。比如这样:

{
    "UserCode": "Admin",
    "Group": "Administrator"
}

我已经尝试创建一个 JsonConverter 并使用以下代码为 Group 属性设置它...

[JsonProperty(ItemConverterType = typeof(StringObjectConverter)]
public UserGroup Group { get; set; }

...和转换器:

class StringObjectConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(ILoadable).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return Activator.CreateInstance(objectType, new object[] { (string)reader.Value });
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue(((ILoadable)value).Code);
    }
}

但它似乎不起作用,因为每次我尝试加载上面看到的 json 时,都会抛出以下异常:

Newtonsoft.Json.JsonSerializationException: 'Error converting value "Administrator" to type 'MyProject.UserGroup'. Path 'Group', line 2, position 10.'

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

我可以在这里使用一些帮助,因为我不知道如何让它工作,即使转换器没有改变任何东西。

【问题讨论】:

  • 另外,PopulateObject 的调用似乎并没有使用我的用户组代码/字符串遇到方法 ReadJson

标签: c# json exception converter populate


【解决方案1】:

您必须使用[JsonConverter(typeof(StringObjectConverter))],而不是[JsonProperty(ItemConverterType = typeof(StringObjectConverter))]

public class User : ILoadable
{
    public User(string code)
    {
        this.Load(code);
    }

    public string Code { get; set; }

    [JsonConverter(typeof(StringObjectConverter))]
    public UserGroup Group { get; set; }
}

注意事项:

  • JsonConverter 指示JsonSerializer 在序列化成员 或类时使用指定的JsonConverter

    您想为UserGroup Group 成员指定一个转换器,所以这是要应用的属性。

  • JsonPropertyAttribute.ItemConverterType 指定在序列化属性的集合项时使用的JsonConverter

    如果你有一个集合,比如List<UserGroup> Groups,并且需要为每个项目指定一个转换器,你会想要应用这个属性。由于您没有集合,因此这不是要使用的正确属性。

    (显然,当 ItemConverterType 应用于其值被序列化为 JSON 对象的成员时,Json.NET 将转换器应用于该对象的每个成员。这有点令人惊讶;我找不到任何地方这是明确记录的。这说明了您看到的异常。)

工作.Net fiddle

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-29
    • 2020-12-12
    • 1970-01-01
    • 2015-10-10
    • 1970-01-01
    • 1970-01-01
    • 2011-08-12
    • 2019-02-15
    相关资源
    最近更新 更多