[英]Dserialise JSON to object. Some properties always the same, some different
I am trying to build a function where a user can upload a json file. 我正在尝试构建一个用户可以上传json文件的功能。
Each row in the json file can have a different nr of properties(ie columns). json文件中的每一行都可以具有不同的nr属性(即列)。 5 of these properties are always the same so I want those to be deserialized to an object. 这些属性中的5个始终相同,因此我希望将其反序列化为对象。 The rest of the properties have to go into a dictionary or something. 其余属性必须放入字典或其他内容中。
Here is a json example: 这是一个json示例:
[{
"Projekt": "Bakker Bouw Service",
"Ruimte": "Hoofdgebouw",
"Apparaat": {
"project": "Bosboom001",
"versie": "812"
},
"Apparaat naam": "",
"Status": "Goedgekeurd",
"Testname1": "",
"Testname3": "2000-01-04T10:37:00+01:00",
"Testname7": "2001-01-03T00:00:00+01:00"
}, {
"Projekt": "Bakker Bouw Service",
"Ruimte": "Hoofdgebouw",
"Apparaat": {
"project": "Vlaams003",
"versie": "713"
},
"Apparaat naam": "",
"Status": "Goedgekeurd",
"Testname1": "Slecht",
"Testname7": "2000-01-04T10:37:00+01:00",
"Testname9": "2001-01-03T00:00:00+01:00",
"Testname16": "18MOhm",
"Testname23": "OK"
}, {
"Projekt": "Bakker Bouw Service",
"Ruimte": "Hoofdgebouw",
"Apparaat": {
"project": "Vlaams017",
"versie": "73"
},
"Apparaat naam": "GDR34Z5",
"Status": "Afgekeurd",
"Testname7": "2000-01-04T10:37:00+01:00",
"Testname10": "0,012mA",
"Testname16": "200MOhm",
"Testname23": "200MOhm",
"Testname25": "Afgekeurd",
"Testname31": "0,01mA"
}
]
Here is the class to deserialze to: 这是要反序列化的类:
public class KeuringRegel
{
public string Projekt { get; set; }
public string Ruimte { get; set; }
public Apparaat Apparaat { get; set; }
[JsonProperty(PropertyName = "Apparaat naam")]
public string Apparaatnaam { get; set; }
public string Status { get; set; }
public Dictionary<string, object> testNames { get; set; }
}
public class Apparaat
{
public string project { get; set; }
public string versie { get; set; }
}
And here is the controller 这是控制器
public IActionResult Upload(IFormFile file)
{
string fileContent = null;
using (var reader = new StreamReader(file.OpenReadStream()))
{
fileContent = reader.ReadToEnd();
}
List<KeuringRegel> keuringRegelList = JsonConvert.DeserializeObject<List<KeuringRegel>>(fileContent);
//More stuff here
}
The json successfully deserializes but the testNames
value is always null. json成功反序列化,但testNames
值始终为null。 I understand why, because there is no testNames
property in the Json file. 我了解原因,因为Json文件中没有testNames
属性。 However, how do I achieve what I want? 但是,我如何实现自己想要的? I am no Json expert. 我不是Json专家。
One way you can do this, assuming that there is only testNameNNNN
entries as supplemental values, is to use the JsonExtensionDataAttribute
like this: 假设只有 testNameNNNN
条目作为补充值,您可以采用以下方法来执行此操作,即使用JsonExtensionDataAttribute
:
public class KeuringRegel
{
public string Projekt { get; set; }
public string Ruimte { get; set; }
public Apparaat Apparaat { get; set; }
[JsonProperty(PropertyName = "Apparaat naam")]
public string Apparaatnaam { get; set; }
public string Status { get; set; }
[JsonExtensionData()]
public Dictionary<string, object> testNames { get; set; }
}
This will give you the values whos don't fall into one of the other properties: 这将为您提供不属于其他属性之一的值:
It's a bit of a "blunt instrument" but you could always perform some post-processing on the returned instances of KeuringRegel
to remove any errant entries from testNames (ie things that don't match the pattern testNameNNNN
). 这有点“笨拙”,但是您始终可以对返回的KeuringRegel
实例执行一些后处理,以从KeuringRegel
中删除所有错误条目(即与testNameNNNN
模式不匹配的testNameNNNN
)。
If your JSON does contain things that don't match the pattern testNameNNNN
which would therefore get included, you could implement a custom class for the testNames
property: 如果您的JSON 确实包含与testNameNNNN
模式不匹配的内容, testNameNNNN
其包含在内,则可testNames
属性实现一个自定义类:
public class KeuringRegel
{
public string Projekt { get; set; }
public string Ruimte { get; set; }
public Apparaat Apparaat { get; set; }
[JsonProperty(PropertyName = "Apparaat naam")]
public string Apparaatnaam { get; set; }
public string Status { get; set; }
[JsonExtensionData()]
public TestNames testNames { get; set; }
}
public class TestNames : Dictionary<string, object>
{
public new void Add(string key, object value)
{
if (key.StartsWith("testname", StringComparison.OrdinalIgnoreCase))
{
base.Add(key, value);
}
}
}
This will check each item that is added to the testNames
dictionary and prevent its addition if (as in my comment where I had an item in the JSON of "badgerBadgetCatCat": 3
) it doesn't match the pattern. 这将检查添加到testNames
词典中的每个项目,并防止其添加(例如,在我的评论中,我在JSON中的"badgerBadgetCatCat": 3
)不匹配该模式。
Here u are full example 这是完整的例子
internal class Program
{
private static void Main(string[] args)
{
var str = @"[{
""Projekt"": ""Bakker Bouw Service"",
""Ruimte"": ""Hoofdgebouw"",
""Apparaat"": {
""project"": ""Bosboom001"",
""versie"": ""812""
},
""Apparaat naam"": """",
""Status"": ""Goedgekeurd"",
""Testname1"": """",
""Testname3"": ""2000-01-04T10:37:00+01:00"",
""Testname7"": ""2001-01-03T00:00:00+01:00""
}, {
""Projekt"": ""Bakker Bouw Service"",
""Ruimte"": ""Hoofdgebouw"",
""Apparaat"": {
""project"": ""Vlaams003"",
""versie"": ""713""
},
""Apparaat naam"": """",
""Status"": ""Goedgekeurd"",
""Testname1"": ""Slecht"",
""Testname7"": ""2000-01-04T10:37:00+01:00"",
""Testname9"": ""2001-01-03T00:00:00+01:00"",
""Testname16"": ""18MOhm"",
""Testname23"": ""OK""
}, {
""Projekt"": ""Bakker Bouw Service"",
""Ruimte"": ""Hoofdgebouw"",
""Apparaat"": {
""project"": ""Vlaams017"",
""versie"": ""73""
},
""Apparaat naam"": ""GDR34Z5"",
""Status"": ""Afgekeurd"",
""Testname7"": ""2000-01-04T10:37:00+01:00"",
""Testname10"": ""0,012mA"",
""Testname16"": ""200MOhm"",
""Testname23"": ""200MOhm"",
""Testname25"": ""Afgekeurd"",
""Testname31"": ""0,01mA""
}
]";
var sw = Stopwatch.StartNew();
var result = Mapper.Map(str);
sw.Stop();
Console.WriteLine($"Deserialized at {sw.ElapsedMilliseconds} ms ({sw.ElapsedTicks} tiks)");
}
public static class Mapper
{
static Mapper()
{
List<string> names = new List<string>();
IEnumerable<PropertyInfo> p = typeof(KeuringRegel).GetProperties().Where(c => c.CanRead && c.CanWrite);
foreach (var propertyInfo in p)
{
var attr = propertyInfo.GetCustomAttribute<JsonPropertyAttribute>();
names.Add(attr != null ? attr.PropertyName : propertyInfo.Name);
}
Properties = names.ToArray();
}
private static string[] Properties { get; }
public static KeuringRegel[] Map(string str)
{
var keuringRegels = JsonConvert.DeserializeObject<KeuringRegel[]>(str);
var objs = JsonConvert.DeserializeObject(str) as IEnumerable;
var objectList = new List<JObject>();
foreach (JObject obj in objs)
objectList.Add(obj);
for (var i = 0; i < keuringRegels.Length; i++)
{
keuringRegels[i].testNames = new Dictionary<string, object>();
foreach (var p in objectList[i].Children().OfType<JProperty>().Where(c => !Properties.Contains(c.Name)).ToArray())
keuringRegels[i].testNames.Add(p.Name, p.Value);
}
return keuringRegels;
}
}
public class KeuringRegel
{
public string Projekt { get; set; }
public string Ruimte { get; set; }
public Apparaat Apparaat { get; set; }
[JsonProperty(PropertyName = "Apparaat naam")]
public string Apparaatnaam { get; set; }
public string Status { get; set; }
public Dictionary<string, object> testNames { get; set; }
}
public class Apparaat
{
public string project { get; set; }
public string versie { get; set; }
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.