更新时间:2022-05-01 07:27:45
您可以使用 json.net ,只要您使用的字符串数组中只有一次,并且对象本身表示为值数组,内部数组与结构数组成1-1对应.
You can use json.net to deserialize and re-serialize a List<LocationChannelEvent>
in the format shown as long as you use a custom JsonConverer
. This is required because, by default, a collection of objects is serialized from and to a JSON array, but in your JSON, a collection of objects is being serialized in a slightly more compact form of a single object where the object property names are serialized only once in an array of strings called "structure"
, and the objects themselves are represented as an array of array of values, the inner arrays being in 1-1 correspondence to the structure array.
因此,如果您创建以下转换器:
Thus, if you create the following converter:
public class StructuredListConverter<T> : JsonConverter
{
const string typeName = "type";
const string structureName = "structure";
const string listName = "list";
public override bool CanConvert(Type objectType)
{
if (!typeof(ICollection<T>).IsAssignableFrom(objectType))
return false;
// This converter is only implemented for read/write collections. So no arrays.
if (objectType.IsArray)
return false;
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var collection = existingValue as ICollection<T> ?? (ICollection<T>) serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
var root = JObject.Load(reader);
var structure = root[structureName] == null ? null : root[structureName].ToObject<string []>();
if (structure == null)
throw new JsonSerializationException("structure not found.");
var listToken = root[listName];
if (listToken == null || listToken.Type == JTokenType.Null)
return collection;
var list = listToken as JArray;
if (list == null)
throw new JsonSerializationException("list was not an array.");
if (list == null || list.Count == 0)
return collection;
foreach (var item in list)
{
if (item == null || item.Type == JTokenType.Null)
collection.Add(default(T));
else if (item.Type != JTokenType.Array)
throw new JsonSerializationException(string.Format("Item was not an array: {0}", item));
else
collection.Add(new JObject(item.Zip(structure, (i, n) => new JProperty(n, i))).ToObject<T>());
}
return collection;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var contract = serializer.ContractResolver.ResolveContract(typeof(T)) as JsonObjectContract;
if (contract == null)
throw new JsonSerializationException(string.Format("Type {0} is not mapped to a JSON object.", typeof(T)));
var collection = (ICollection<T>)value;
writer.WriteStartObject();
// Write item type
writer.WritePropertyName(typeName);
serializer.Serialize(writer, typeof(T));
// Write structure (property names)
var structure = contract.Properties.Where(p => p.Readable && !p.Ignored).Select(p => p.PropertyName).ToList();
writer.WritePropertyName(structureName);
serializer.Serialize(writer, structure);
// Write array of array of values
var query = collection
.Select(i => i == null ? null : contract.Properties.Where(p => p.Readable && !p.Ignored).Select(p => p.ValueProvider.GetValue(i)));
writer.WritePropertyName(listName);
serializer.Serialize(writer, query);
writer.WriteEndObject();
}
}
并按如下所示定义数据模型:
And define your data model as follows:
public class LocationChannelEvent : Activity.Channel.Event
{
public double Latitude { get; set; }
public double Longitude { get; set; }
public float? Distance { get; set; }
public float? Altitude { get; set; }
/// <summary>
/// Speed in m/s
/// </summary>
public float? Speed { get; set; }
}
public class Location
{
[JsonConverter(typeof(StructuredListConverter<LocationChannelEvent>))]
public List<LocationChannelEvent> events { get; set; }
}
public class RootObject
{
public Location location { get; set; }
}
您将能够反序列化并重新序列化所显示的JSON.
You will be able to deserialize and re-serialize the JSON shown.
原型小提琴.