newtonsoft.json反序列化逻辑

时间:2015-05-12 20:12:21

标签: c# json.net

我正在尝试在反序列化期间将一个带有例如[1,2,3]的json字符串解析为数组。

这是我的json数据:

[
    {
        "id": "1",
        "district": "1",
        "lon": "4.420650000000000000",
        "lat": "51.21782000000000000",
        "bikes": "19",
        "slots": "14",
        "zip": "2018",
        "address": "Koningin Astridplein",
        "addressNumber": null,
        "nearbyStations": "3,4,5,24",
        "status": "OPN",
        "name": "001- Centraal Station - Astrid"
    }
]

这是我的c#当前映射到常规字符串,我希望它是一个整数数组。

var AvailabilityMap = new[] { new Station() };
var data = JsonConvert.DeserializeAnonymousType(json, AvailabilityMap);

public class Station
{
    public int Id { get; set; }
    public double Lon { get; set; }
    public double Lat { get; set; }
    public int Bikes { get; set; }
    public int Slots { get; set; }
    public string Address { get; set; }
    public string NearbyStations { get; set; }
    public string Status { get; set; }
    public string Name { get; set; }
}

到目前为止,我没有找到以正确方式执行此操作的方法,而无需再次循环使用当前数组..

3 个答案:

答案 0 :(得分:4)

创建自定义转换器。像这样:

PropertyChangedHandler

现在更改您的课程以使用aViewModel.OnPropertyChanged( handler: p => FooBarBazCommand.Invalidate(), properties: aViewModel.GetProperties( p => p.Foo, p => p.Bar, p => p.Baz ) );

来使用转换器
public class StringToIntEnumerable : JsonConverter
{

    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }

    public override bool CanWrite
    {
        get
        {
            return false;    // we'll stick to read-only. If you want to be able 
                             // to write it isn't that much harder to do.
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // Note: I've skipped over a lot of error checking and trapping here
        // but you might want to add some
        var str = reader.Value.ToString();
        return str.Split(',').Select(s => int.Parse(s));
    }

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

现在要反序列化:

JsonConverterAttribute

答案 1 :(得分:2)

Here is a working fiddle使用自定义JsonConverter

我们正在做的是在将整个JSON字符串转换为Station对象之前,将CSV值转换为正确的JSON数组

自定义JsonConverter

ReadJson读取JSON字符串。首先,它将JSON加载到JObject。接下来,它获取nearbyStations属性并将其从简单的CSV字符串更改为JavaScript数组。它通过将CSV包装在方括号内来实现。最后,我们使用JsonSerializer填充目标对象并将其返回。

CanWrite设置为false,因为此JsonConverter只允许读取JSON而不是写入JSON。因此,我们不需要实施WriteJsonCanConvert测试以确保目标对象是Station

public class StationConverter : JsonConverter
{
    public override object ReadJson(
        JsonReader r, Type t, object v, JsonSerializer s)
    {
        JObject jObject = JObject.Load(r);

        var prop = jObject.Property("nearbyStations");
        var wrapped = string.Format("[{0}]", prop.Value);
        JArray jsonArray = JArray.Parse(wrapped);
        prop.Value = jsonArray;

        var target = new Station();
        s.Populate(jObject.CreateReader(), target);

        return target;
    }

    public override void WriteJson(JsonWriter w, object v, JsonSerializer s)
    {
        throw new NotImplementedException("Unnecessary: CanWrite is false.");
    }

    public override bool CanWrite
    {
        get { return false; }
    }

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

Station类更改为int[]

要使上述JsonConverter生效,请将您的NearbyStations媒体资源更改为int[]

public int[] NearbyStations
{
    get;
    set;
}

用法示例with Live Fiddle

以下是如何使用它的示例:

var AvailabilityMap = 
    JsonConvert.DeserializeObject<Station[]>(json, new StationConverter());

Console.WriteLine(AvailabilityMap[0].NearbyStations[0]);

答案 2 :(得分:1)

正确的答案是输入格式正确。在这种情况下:

 "nearbyStations": ["3","4","5","24"]

但我遇到了类似无法更新数据的情况,因此必须找到解决方案。最简单的方法是制作一个不会被串行器/解串器触及的getter / setter。不幸的是,您无法使用此序列化程序忽略公共属性。所以你必须做一些聪明的解决方法,比如阅读DTO并使用业务对象进行实际操作。

public class StationDTO
{
    public int Id { get; set; }
    public double Lon { get; set; }
    public double Lat { get; set; }
    public int Bikes { get; set; }
    public int Slots { get; set; }
    public string Address { get; set; }
    public string NearbyStations { get; set; }
    public string Status { get; set; }
    public string Name { get; set; }
}

...

public class Station : StationDTO
{
    public List<string> NearbyStationsList
    { 
        get 
        {
            return NearbyStations.Split(',');
        }

        set
        {
            NearbyStations = string.Join(",", value);
        }
    }
}

更多信息:Newtonsoft ignore attributes?