2017-08-02 54 views
3

我有以下的JSON字符串作为我的问题的例子:反序列化列表<string>从JSON来列出<object>

{ 
    "Code": "Admin", 
    "Groups": 
    [ 
     "Administrator", 
     "Superuser", 
     "User" 
    ] 
} 

而且我有一个名为用户使用如下代码类...

[JsonObject(MemberSerialization.OptIn)] 
public class User 
{ 
    public User (string code) 
    { 
     this.Code = code; 
    } 

    [JsonProperty] 
    public string Code { get; set; } 

    [JsonProperty("Groups")] 
    private List<UserGroup> groups; 
    public List<UserGroup> Groups 
    { 
     if (groups == null) 
      groups = new List<UserGroup>(); 
     return groups; 
    } 
} 

...和一个名为用户组类 - 在这个例子 - 只有这几行代码:

public class UserGroup 
{ 
    public UserGroup (string code) 
    { 
     this.Code = code; 

     // Some code to fill all the other properties, just by knowing the code. 
    } 

    public string Code { get; set; } 

    // More properties 
} 

现在,我想要的是,上面显示的JSON字符串将被反序列化为一个用户的实例,并且“Groups”数组中的所有字符串都应该反序列化为带有来自每个字符串的实例的List<UserGroup>。 此外 - 另一种方式 - 应该将用户序列化为只包含UserGroups的Code属性的JSON字符串。

我通常不反序列化,但我创建一个用户的实例,并使用此代码填充它...

Newtonsoft.Json.JsonConvert.PopulateObject(jsonString, myUserInstance); 

...但如果我用上面所示的JSON字符串运行代码的所有我得到的是以下情况例外:

Newtonsoft.Json.JsonSerializationException: 'Error converting value "Administrator" to type 'UserGroup'. 

我最后的要求是,我想UserGroup被序列化为一个字符串数组只有当我序列化User。当我将一个UserGroup独立作为一个根对象序列化时,它应该正常序列化(具有所有属性)。 (作为比较,在Json.Net: Serialize/Deserialize property as a value, not as an object中,对象在所有情况下都被串行化为一个字符串。)

+2

两个选项。创建一个自定义JsonConverter,知道如何处理转换或向类中添加隐式运算符以知道如何从字符串转换 – Nkosi

+0

是否必须创建从String到UserGroup的JsonConverter以及从字符串到列表的其他方式oder List ? 你是什么意思加入一个隐式运算符? –

+0

只是好奇,为什么不使用这个? [JsonProperty(“Groups”)] public string [] Groups {get;组; } –

回答

2

你将不得不写一个转换器为UserGroup

这是基于什么样的问题

被描述一个简单的转换
public class UserGroupJsonConverter : JsonConverter { 

    public override bool CanConvert(Type objectType) { 
     return typeof(UserGroup) == objectType; 
    } 

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

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

,然后更新User通过设置在JsonProperty属性的ItemConverterType要注意转换器的

[JsonObject(MemberSerialization.OptIn)] 
public class User { 
    public User(string code) { 
     this.Code = code; 
    } 

    [JsonProperty] 
    public string Code { get; set; } 

    private List<UserGroup> groups; 
    [JsonProperty("Groups", ItemConverterType = typeof(UserGroupJsonConverter))] 
    public List<UserGroup> Groups { 
     get { 
      if (groups == null) 
       groups = new List<UserGroup>(); 
      return groups; 
     } 
    } 
} 

现在这将允许JSON在示例

{ 
    "Code": "Admin", 
    "Groups": 
    [ 
     "Administrator", 
     "Superuser", 
     "User" 
    ] 
} 

如期望

var user = JsonConvert.DeserializeObject<User>(json); 

和被序列回到相同的格式被反序列化。

var json = JsonConvert.SerializeObject(user); 
+0

如果我这样做,例如不想序列化我的用户,但也许用户组本身,它不使用此转换器(如果我不告诉它),但会正常序列化它,与财产名称等,对吗? –

+0

@ChristophMett,是的。在上面的例子中,该属性只应用于'User'对象的'Groups'属性。如果你想仅仅序列化'UserGroup'对象,则转换器不适用。 – Nkosi

0

Administrator是一个字符串,UserGroup是一个对象,所以这是一个类型不匹配。在你的代码中规定的情况下有效的JSON是:

{ 
    "Code": "Admin", 
    "Groups": 
    [ 
     { 
      "Code":"Administrator" 
     }, 
     { 
      "Code":"Superuser" 
     }, 
     { 
      "Code":"User" 
     } 
    ] 
} 
+0

通常这是完全正确的,但在我的示例中,我不想将UserGroup的整个对象结构保存在JSON字符串中,但仅保存代码。 代码属性足以让我的代码获取整个UserGroup实例。因此,为了不保存冗余数据(我知道,它是JSON的一个几乎必不可少的部分)我只想从JSON的代码属性中保存字符串,并且还希望反序列化从整个UserGroup实例中获取代码字符串。 –