JSon.Net反序列化自定义类

时间:2016-06-25 18:12:28

标签: c# json serialization json.net

我想将json对象反序列化为自定义类。该课程可能如下所示:

public class CommunicationMessage {

    public string Key { get; set; }

    public string Value { get; set; }

    public List<CommunicationMessage> Childs { get; set; }
}

我希望反序列化的json看起来像这样:

{
"Skills": [{
    "Skill": [{
        "SkillID": "1",
        "ParticipantID": "7",
        "CanDo": "True"
    }, {
        "SkillID": "2",
        "ParticipantID": "7",
        "CanDo": "True"
    }, {
        "SkillID": "3",
        "ParticipantID": "7",
        "CanDo": "False"
    }]
}]
}

这是我用来反序列化json的代码:

private void ReadRecursive(JToken token, ref CommunicationMessage root) {

        if (token is JProperty) {

            CommunicationMessage msg = new CommunicationMessage();

            if (token.First is JValue) {
                msg.Key = ((JProperty)token).Name;
                msg.Value = (string)((JProperty)token).Value;
            } else {

                msg.Key = ((JProperty)token).Name;

                foreach (JToken child in token.Children()) {
                    ReadRecursive(child, ref msg);
                }
            }
            root.Childs.Add(msg);
        } else {
            foreach (JToken child in token.Children()) {
                ReadRecursive(child, ref root);
            }
        }
    }

我期待得到这个hirarchy:

Skills
    Skill
         SkillID:1
         ParticipantID:7
         CanDo:true
    Skill
         SkillID:2
         ParticipantID:7
         CanDo:true
    Skill
         SkillID:3
         ParticipantID:7
         CanDo:false

但我得到了这个:

Skills
    Skill
         SkillID:1
         ParticipantID:7
         CanDo:
         SkillID:2
         ParticipantID:7
         CanDo:true
         SkillID:3
         ParticipantID:7
         CanDo:false

我无法找到失败的地方,所以也许有人可以帮助我。

谢谢!

4 个答案:

答案 0 :(得分:1)

你的代码似乎做得很好(虽然有更简单的方法来实现你的目标)。有问题的部分是它自己的JSON。它分为两个阵列。

因此,您的代码会输出Skills - 数组(包含一个元素)和Skill - 数组,其中包含您期望的实际3项技能。

{
    "Skills": [{        // array -> note the [
        "Skill": [{     // array -> note the [

因此解决这个问题的一种方法是编辑JSON(如果可能的话):

{
    "Skills": [{
        "SkillID": "1",
        "ParticipantID": "7",
        "CanDo": "True"
    }, {
        "SkillID": "2",
        "ParticipantID": "7",
        "CanDo": "True"
    }, {
        "SkillID": "3",
        "ParticipantID": "7",
        "CanDo": "False"
    }]
}

答案 1 :(得分:0)

使用Newtonsoft Json.NET

output message = JsonConvert.DeserializeObject<CommunicationMessage>(json);

(其中json是JSON字符串。)

我使用此页面 - json2csharp - 创建与您发布的JSON相匹配的类:

public class Skill2
{
    public string SkillID { get; set; }
    public string ParticipantID { get; set; }
    public string CanDo { get; set; }
}

public class Skill
{
    public List<Skill2> Skill { get; set; }
}

public class CommunicationMessage
{
    public List<Skill> Skills { get; set; }
}

类名是自动生成的。它始终命名根对象RootObject。但你可以把它改成CommunicationMessage(我做过。)

如果您希望该类具有与JSON不匹配的不同属性名称,则可以使用属性执行该操作。

public class Skill2
{
    [JsonProperty["Key"]
    public string SkillID { get; set; }
    [JsonProperty["Value"]
    public string ParticipantID { get; set; }
    public string CanDo { get; set; }
}

答案 2 :(得分:0)

使用DataContractJsonSerializer中的System.Runtime.Serialization可以更轻松地进行反序列化:

Stream data = File.OpenRead(@"data.json");
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(CommunicationMessage));
CommunicationMessage message = (CommunicationMessage)serializer.ReadObject(data);

但你还需要一个这样的课程:

[DataContract]
class CommunicationMessage
{
    [DataContract]
    class SkillsData
    {
        [DataContract]
        internal class SkillData
        {
            [DataMember(Name = "SkillID")]
            internal object SkillID;
            [DataMember(Name = "ParticipantID")]
            internal object ParticipantID;
            [DataMember(Name = "CanDo")]
            internal object CanDo;
        }


        [DataMember(Name = "Skill")]
        internal SkillData[] Skill;
    }


    [DataMember(Name = "Skills")]
    SkillsData[] Skills;
}

上面有班级SkillData,其中包含每项技能的数据。因此,如果您使用数组Skill,您就可以获得所需的hirarchy。

答案 3 :(得分:0)

您可以使用递归方法中的逻辑检查何时处于正确的级别/对象类型。

getExpirationTime