我将此JSON数组作为输入。
[
{
"FirstName": "Test1",
"LastName": "Test2",
"Address": "London, GB",
"Error": "Something's gone wrong"
},
{
"FirstName": "Test3",
"LastName": "Test4",
"Address": "NewYork, US",
"Error": "Something's gone wrong"
},
{
"DisplayName": "ContactNumber",
"Value": "01234 123 123"
}
]
我想在C#
中构建一个像这样的JSON对象[
"pages":{
"FirstName": "Test1",
"LastName": "Test2",
"Address": "London, GB",
"Error": "Something's gone wrong"
},
{
"FirstName": "Test3",
"LastName": "Test4",
"Address": "NewYork, US",
"Error": "Something's gone wrong"
},
"labels": {
"DisplayName": "ContactNumber",
"Value": "01234 123 123"
}
}
]
我创建了一个具有上述输出属性的模型,但是当我将对象反序列化为该模型时,它们没有被映射。所有值都返回null。
var deserializedData = JsonConvert.DeserializeObject<List<Config>>(serializedData);
我检查时收到的回复是
[
{
"pages": null,
"labels": null
},
{
"pages": null,
"labels": null
}
]
任何人都可以帮助我在 C#中为我想要的格式构建自定义模型。
提前致谢。
答案 0 :(得分:0)
你的json是无效的json结构进行解析,这根本无效(请在这里检查它有什么问题:https://jsonlint.com/)
无效的json字符串
[
"pages":{
"FirstName": "Test1",
"LastName": "Test2",
"Address": "London, GB",
"Error": "Something's gone wrong"
},
{
"FirstName": "Test3",
"LastName": "Test4",
"Address": "NewYork, US",
"Error": "Something's gone wrong"
},
"labels": {
"DisplayName": "ContactNumber",
"Value": "01234 123 123"
}
}
]
但是我给你修好了json
修复并正常工作json
[{
"pages": [{
"FirstName": "Test1",
"LastName": "Test2",
"Address": "London, GB",
"Error": "Something's gone wrong"
},
{
"FirstName": "Test3",
"LastName": "Test4",
"Address": "NewYork, US",
"Error": "Something's gone wrong"
}
],
"labels": {
"DisplayName": "ContactNumber",
"Value": "01234 123 123"
}
}]
应用修复json后,您的C#对象
public class Page
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string Error { get; set; }
}
public class Labels
{
public string DisplayName { get; set; }
public string Value { get; set; }
}
public class RootObject
{
public List<Page> pages { get; set; }
public Labels labels { get; set; }
}
我尝试使用我的固定json并且工作正常。
编辑结束
下面的代码对我来说很合适,我在下面提供了类结构
列表
var jsonString = "[{ \"pages\": {\"id\": 12345, \"name\": \"John Doe\", \"number\": \"123\", \"test\": "+
"\"John\" }, \"labels\": { \"test\": \"test1\", \"test2\": \"test2\" } }," +
"{ \"pages\": {\"id\": 12345, \"name\": \"John Doe\", \"number\": \"123\", \"test\": "+
"\"John\" }, \"labels\": { \"test\": \"test1\", \"test2\": \"test2\" } }]";
var deserializedData = JsonConvert.DeserializeObject<List<RootObject>>(jsonString);
以单个对象作为输入
var jsonString = "{ \"pages\": {\"id\": 12345, \"name\": \"John Doe\", \"number\": \"123\", \"test\": "+
"\"John\" }, \"labels\": { \"test\": \"test1\", \"test2\": \"test2\" } }";
var deserializedData = JsonConvert.DeserializeObject<RootObject>(jsonString);
基于输入
{ "pages": { "id": 12345, "name": "John Doe", "number": "123", "test":
"John" }, "labels": { "test": "test1", "test2": "test2" } }
下面是生成的类
public class Pages
{
public int id { get; set; }
public string name { get; set; }
public string number { get; set; }
public string test { get; set; }
}
public class Labels
{
public string test { get; set; }
public string test2 { get; set; }
}
public class RootObject
{
public Pages pages { get; set; }
public Labels labels { get; set; }
}
如果你有Json,那么你可以使用visual studio本身生成C#类。
在视觉工作室中查找&#34;粘贴Sepcial&#34;菜单。即复制json字符串并单击Paste special,它将为您生成C#类。
您可以关注我的帖子:Generate Class From JSON or XML in Visual Studio
或使用以下在线网站:json2csharp
答案 1 :(得分:0)
您所拥有的是包含各种类型对象的多态JSON数组,可通过特定属性("DisplayName"
vs "FirstName"
的存在来区分,例如)。您想要做的是将其反序列化为c#模型,其中每个可能的数组项都被添加到模型的集合值属性中,其中选择集合属性以具有正确的项类型。
这可以通过使用custom JsonConverter
来完成。由于问题陈述是通用的,我将使转换器成为通用的。硬编码转换器需要的代码更少。
首先,按如下方式定义您想要的模型:
public class Page
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string Error { get; set; }
}
public class Label
{
public string DisplayName { get; set; }
public string Value { get; set; }
}
public class RootObject
{
public List<Page> pages { get; set; }
public List<Label> labels { get; set; }
}
接下来定义以下转换器:
public class PolymorphicArrayToObjectConverter<TObject> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(TObject).IsAssignableFrom(objectType);
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
static JsonObjectContract FindContract(JObject obj, IEnumerable<Type> derivedTypes, JsonSerializer serializer)
{
List<JsonObjectContract> bestContracts = new List<JsonObjectContract>();
foreach (var type in derivedTypes)
{
if (type.IsAbstract)
continue;
var contract = serializer.ContractResolver.ResolveContract(type) as JsonObjectContract;
if (contract == null)
continue;
if (obj.Properties().Select(p => p.Name).Any(n => contract.Properties.GetClosestMatchProperty(n) == null))
continue;
if (bestContracts.Count == 0 || bestContracts[0].Properties.Count > contract.Properties.Count)
{
bestContracts.Clear();
bestContracts.Add(contract);
}
else if (contract.Properties.Count == bestContracts[0].Properties.Count)
{
bestContracts.Add(contract);
}
}
return bestContracts.Single();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
else if (reader.TokenType != JsonToken.StartArray)
throw new InvalidOperationException("JSON token is not an array at path: " + reader.Path);
var contract = (JsonObjectContract)serializer.ContractResolver.ResolveContract(objectType);
existingValue = existingValue ?? contract.DefaultCreator();
var lookup = contract
.Properties
.Select(p => new { Property = p, PropertyContract = serializer.ContractResolver.ResolveContract(p.PropertyType) as JsonArrayContract })
.Where(i => i.PropertyContract != null)
.ToDictionary(i => i.PropertyContract.CollectionItemType);
var types = lookup.Select(i => i.Key).ToList();
while (reader.Read())
{
switch (reader.TokenType)
{
case JsonToken.Comment:
break;
case JsonToken.EndArray:
return existingValue;
default:
{
var itemObj = JObject.Load(reader);
var itemContract = FindContract(itemObj, types, serializer);
if (itemContract == null)
continue;
var item = serializer.Deserialize(itemObj.CreateReader(), itemContract.UnderlyingType);
var propertyData = lookup[itemContract.UnderlyingType];
var collection = propertyData.Property.ValueProvider.GetValue(existingValue);
if (collection == null)
{
collection = propertyData.PropertyContract.DefaultCreator();
propertyData.Property.ValueProvider.SetValue(existingValue, collection);
}
collection.GetType().GetMethod("Add").Invoke(collection, new [] { item });
}
break;
}
}
// Should not come here.
throw new JsonSerializationException("Unclosed array at path: " + reader.Path);
}
}
然后,反序列化并重新序列化您的RootObject
集合,如下所示:
var settings = new JsonSerializerSettings
{
Converters = { new PolymorphicArrayToObjectConverter<RootObject>() },
};
var root = new List<RootObject> { JsonConvert.DeserializeObject<RootObject>(jsonString, settings) };
var outputJson = JsonConvert.SerializeObject(root, Formatting.Indented);
结果,将生成以下JSON:
[
{
"pages": [
{
"FirstName": "Test1",
"LastName": "Test2",
"Address": "London, GB",
"Error": "Something's gone wrong"
},
{
"FirstName": "Test3",
"LastName": "Test4",
"Address": "NewYork, US",
"Error": "Something's gone wrong"
}
],
"labels": [
{
"DisplayName": "ContactNumber",
"Value": "01234 123 123"
}
]
}
]
示例fiddle。
注 - 自动推断数组项类型的代码改编自this answer。