JsonConvert字符串到集合

时间:2018-04-25 17:54:53

标签: c# json deserialization

我从API获取此json格式:

"url_service": "",
"Description": null,
"Target": "5,6",
"Category ": "2"

我试图将json反序列化为模型。问题出在" Target"应该是int的ICollection的字段。 这是我的模特:

public string Description{ get; set; }
public ICollection<int> Target{ get; set; }
public int Category { get; set; }

有没有办法在序列化之前处理Json,以便从逗号分隔的字符串中创建一个集合?

4 个答案:

答案 0 :(得分:1)

不是试图更改反序列化逻辑,为什么不让自己更容易,只在模型中包含一个新属性?

public string Description{ get; set; }
public int Category { get; set; }

//Change this back to string, since that is what your JSON is
public string Target{ get; set; }

//Add a "TargetList" property that just reads from "Target" and turns into a List
public List<int> TargetList => Target.Split(',').Select(x => int.Parse(x)).ToList();

请注意,我的代码中没有错误处理,因此您必须相应地进行修改。

答案 1 :(得分:0)

是的,让您的C#类实现ISerializable接口。你可以实现OnDeserialized(),OnSerialized()函数。

请参阅.NET Deserialisation with OnDeserializing and OnDeserialized

答案 2 :(得分:0)

您的JSON片段不描述整数集合,而是描述字符串。正确的是

"Target": [ 5, 6 ],

转换为

的JSON模式
 "Target": {
     "type": ["array"],
     "items": { "type": "integer"}
    },

如果您无法控制结果,则创建另一个属性,该属性将是整数的结果,例如

   private string _target;
   public string Target {  get { return _target; } 
                           set { 
                                 _target = value; 
                                 Targets = Regex.Matches(_target, @"(\d+)")
                                                .OfType<Match>()
                                                .Select(mt => int.Parse(mt.Value))
                                                .ToList();
   public List<int> Targets { get; set; }

答案 3 :(得分:0)

目标字段在json中是字符串类型,因此序列化程序将尝试将其作为字符串读取。 您可以使用转换器来取代它,例如使用Newtonsoft Json

让我们假设您的数据结构定义如下:

public class Data {
    public string Description{ get; set; }
    public ICollection<int> Target{ get; set; }
    public int Category { get; set; }
}

然后您可以按如下方式创建自己的JsonConverter

public class DataConverter : JsonConverter {

    public override bool CanWrite => false;

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {

        var jObject = JObject.Load(reader);

        var data = new Data();

        if (jObject.TryGetValue("Description", out JToken jDescription)) {
            data.Description = jDescription.Value<string>();
        }
        if (jObject.TryGetValue("Target", out JToken jTarget)) {
            data.Target = ToTarget(jTarget, serializer);
        }
        if (jObject.TryGetValue("Category", out JToken jCategory)) {
            data.Category = jCategory.Value<int>();
        }

        return req;

    }

    private static ICollection<int> ToTarget( JToken jTarget, JsonSerializer serializer ) {

        int defaultValue = -1;
        var target = new List<int>();
        var collection = jTarget.Value<string>().Split(',');
        foreach (string str in collection)
            if (int.TryParse(str, out int number))
                target.Add(number);
            else
                target.Add(defaultValue);

        return target;

    }

    public override bool CanConvert(Type objectType) => objectType == typeof(Data);

}

然后,您可以使用以下代码进行反序列化:

var jsonSettings = new JsonSerializerSettings();
jsonSettings.Converters.Add(new DataConverter);
Data data = JsonConvert.DeserializeObject<Data>(yourJsonString, jsonSettings);

进一步的考虑:这种方法在数据定义和数据解析逻辑之间提供了清晰的分离,从而保持数据结构和定义不受任何json特定信息和解析逻辑的影响。