如何使用包含“原始”JSON的字符串成员序列化和反序列化类型,而无需在进程中转义JSON

时间:2016-11-10 13:43:34

标签: c# json serialization deserialization

我想将JSON反序列化为Object但我不想反序列化嵌套的JSON,嵌套的嵌套JSON应转换为JSON列表(请检查“我的预期输出”以获得清晰的想法)。 ..

//假设我有以下JSON数据,这里我为“地址”实体

嵌套了JSON
String jsonEmployees =
"{"Employees":
[{"EmpId":1, "EmpName":"ABC", "Address":[{"AddressId":1, "Address":"Something"},{"AddressId":2, "Address":"Anything"}]},
{"EmpId":2, "EmpName":"XYZ", "Address":[{"AddressId":1, "Address":"Something"},{"AddressId":2, "Address":"Anything"}]}]
}"

public class Employee
{
    public int EmpId { get; set; }
    public string EmpName { get; set; }
    // **Note** : I'm not using List<Address> data type for Address, instead of I want list of address in JSON string
    public string Address { get; set; }
}

public class RootObject
{
    public List<Employee> Employees { get; set; }
}

var Employees = JsonConvert.DeserializeObject<RootObject>(jsonEmployees);

//我的预期输出

Employees[0].EmpId = 1;
Employees[0].EmpName = "ABC";
Employees[0].Address = "[{"AddressId":1, "Address":"Something"},{"AddressId":2, "Address":"Anything"}]";

Employees[1].EmpId = 2;
Employees[1].EmpName = "XYZ";
Employees[1].Address = "[{"AddressId":1, "Address":"Something"},{"AddressId":2, "Address":"Anything"}]";

请建议我解决此问题的最佳方法......

3 个答案:

答案 0 :(得分:6)

您的问题是,如何使用包含&#34; raw&#34;的string成员序列化和反序列化类型? JSON,没有在进程中转义JSON?

这可以通过使用custom JsonConverterJsonWriter.WriteRawValue()读取和写入原始JSON的JRaw.Create()来完成:

public class RawConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var raw = JRaw.Create(reader);
        return raw.ToString();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var s = (string)value;
        writer.WriteRawValue(s);
    }
}

然后将其应用于您的类型,如下所示:

public class Employee
{
    public int EmpId { get; set; }
    public string EmpName { get; set; }
    // **Note** : I'm not using List<Address> data type for Address, instead of I want list of address in JSON string
    [JsonConverter(typeof(RawConverter))]
    public string Address { get; set; }
}

public class RootObject
{
    public List<Employee> Employees { get; set; }
}

示例fiddle

请注意,原始JSON字符串必须表示有效的JSON。如果没有,那么创建的JSON将是不可读的。如果要保证JSON文字有效,可以在内部将JSON保持在解析状态:

public class Employee
{
    public int EmpId { get; set; }
    public string EmpName { get; set; }

    [JsonProperty("Address")]
    JToken AddressToken { get; set; }

    [JsonIgnore]
    public string Address
    {
        get
        {
            if (AddressToken == null)
                return null;
            return AddressToken.ToString(Formatting.Indented); // Or Formatting.None if you prefer
        }
        set
        {
            if (value == null)
                AddressToken = null;
            else
                // Throw an exception if value is not valid JSON.
                AddressToken = JToken.Parse(value);
        }
    }
}

此实施不需要转换器。

答案 1 :(得分:1)

我认为你必须重建员工名单:

        RootObject Employees = JsonConvert.DeserializeObject<RootObject>(jsonEmployees);

        List<Employee> EmployeesNew = new List<Employee>();

        foreach (var item in Employees.Employees)
        {
            string StringAddress = JsonConvert.SerializeObject(item.Address, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
            EmployeesNew.Add(new Employee { EmpId = item.EmpId, EmpName = item.EmpName, AddressString = StringAddress });

        }

你的班级:

    public class Employee
    {
        public int EmpId { get; set; }
        public string EmpName { get; set; }
        // **Note** : I'm not using List<Address> data type for Address, instead of I want list of address in JSON string
        public List<AddressItems> Address { get; set; }
        public string AddressString { get; set; }
    }

    public class RootObject
    {
        public List<Employee> Employees { get; set; }
    }

    public class AddressItems
    {
        public int AddressId { get; set; }
        public string Address { get; set; }
    }

答案 2 :(得分:0)

在JSON中,大括号{}是对象的符号,方括号[]用于数组。

只要您的数组封装在大括号中,您就必须使用另一个包含对象。如果您可以删除{"Employees":前缀和}后缀,则应该能够直接将JSON转换为员工列表。

编辑:对不起,我不明白这个问题。

根据您是否可以控制JSON,执行您想要的操作非常简单或非常困难。

如果你可以控制JSON,你需要做的只是在地址值周围添加单引号,所以它看起来像这样:

[{"EmpId":1, "EmpName":"ABC", "Address":'[{"AddressId":1, "Address":"Something"},{"AddressId":2, "Address":"Anything"}]'},

就是这样!现在序列化器将它转换为字符串。

如果你不能,你必须自己反序列化JSON,令牌令牌。或者,您可以执行一种解决方法,创建相应的地址类,并让序列化程序转换为它。然后添加一个计算属性并使用序列化程序将地址反序列化为JSON (丑陋,我知道,但实施起来要快得多)。