我正在从from服务获取JSON数据。它为我提供了具有不同问题和答案的FORM DATA。every answer is a different c# object
。我正在尝试找到将答案映射到正确的c#对象的最佳方法。
例如,如果问题Id是"37“,则它是一个Address对象。
我有如下格式的JSON字符串
"answers": {
"37": {
"name": "yourAddress37",
"order": "6",
"sublabels": "{\"cc_firstName\":\"First Name\",\"cc_lastName\":\"Last Name\",\"cc_number\":\"Credit Card Number\",\"cc_ccv\":\"Security Code\",\"cc_exp_month\":\"Expiration Month\",\"cc_exp_year\":\"Expiration Year\",\"addr_line1\":\"Street Address\",\"addr_line2\":\"Street Address Line 2\",\"city\":\"City\",\"state\":\"State \\/ Province\",\"postal\":\"Postal \\/ Zip Code\",\"country\":\"Country\"}",
"text": "Your Home Address:",
"type": "control_address",
"answer": {
"addr_line1": "148 east 38st ",
"addr_line2": "",
"city": "Brooklyn ",
"state": "Ny",
"postal": "11203",
"country": ""
},
"prettyFormat": "Street Address: 148 east 38st <br>City: Brooklyn <br>State / Province: Ny<br>Postal / Zip Code: 11203<br>"
},
"38": {
"name": "emergencyContact",
"order": "9",
"sublabels": "{\"prefix\":\"Prefix\",\"first\":\"First Name\",\"middle\":\"Middle Name\",\"last\":\"Last Name\",\"suffix\":\"Suffix\"}",
"text": "Emergency Contact Name:",
"type": "control_fullname",
"answer": {
"first": "Pauline ",
"last": "Sandy "
},
"prettyFormat": "Pauline Sandy "
}
}
并且它映射到以下c#属性
public Dictionary<int, answer> answers{ get; set; }
然后我有一个通用的答案类
public class answer
{
public string name { get; set; }
public dynamic answer { get; set; }
}
如果你看看json的答案数据,你会发现每个问题的答案都是不同的。例如,一个答案是ADDRESS对象,另一个答案是名字和姓氏对象。
我的问题是,如何自动将json反序列化为正确的对象/属性?我可以创建不同的POCO对象,比如address和ProfileName,但是我如何将它们自动映射到正确的对象/属性。
编辑:
Loop through all Answers
foreach (var a in item.answers)
{
// pass the ANSWER OBJECT (dynamic data type) to function
createNewApplication(System.Convert.ToInt16(a.Key), a.Value.answer,ref app);
}
private void createNewApplication(int key, dynamic value,ref HcsApplicant app)
{
if (key == 4) // data is plain string
app.yourPhone = value;
if (key == 8)
app.yourEmail = value;
if (key==37) // data is a object
app.address = value.ToObject<address>();
}
这种方法可以吗?有没有更干净的方法呢?
发布于 2019-06-26 08:31:06
通过解析JSON对象字符串为每个answer类型构造一个构造函数。使所有答案都实现一个接口,例如IAnswer。将所有构造函数(作为函数)映射到字典中相应的问题in。最后,遍历问题,调用每个构造函数,并可能将它们放入新的字典中。示例代码:
interface IAnswer { };
public class ExampleAnswer : IAnswer
{
public ExampleAnswer(String JSONObject)
{
// Parse JSON here
}
}
delegate IAnswer AnswerConstructor(String JSONObject);
Dictionary<int, AnswerConstructor> Constructors = new Dictionary<int, AnswerConstructor>()
{
{1234, ((AnswerConstructor)(json => new ExampleAnswer(json)))}
// Add all answer types here
};
Dictionary<int, IAnswer> ParseAnswers(Dictionary<int, String> JSONObjects)
{
var result = new Dictionary<int, IAnswer>();
foreach (var pair in JSONObjects)
result.Add(pair.Key, Constructors[pair.Key](pair.Value));
return result;
}
编辑:查看Matt的答案,了解如何解析JSON的一些很好的选项。
Edit2,回应您的编辑:这看起来是一个很好的方法!我认为这比我的答案更好,因为你可以保留所有的类型信息,不像我的方法。
我认为您可能想要更改的唯一一件事是使用else if
或switch
而不是多个if。如果你有很多答案,这可以提高性能。
发布于 2019-06-26 11:28:14
我个人并不喜欢每一个涉及自定义解析和直接查看问题的选项。
您可以通过JToken
类使用部分反序列化。
只需这样声明您的answers
字典:
public Dictionary<int, JToken> Answers{ get; set; }
然后,当您需要地址页面时,您可以简单地执行Answers[37].ToObject<Address>()
。如何调用此方法取决于代码的其余部分,但您可以将其嵌入到属性中,在一个大开关中,在多个方法中,每个类一个。我喜欢的一个选择是在每个可反序列化的类中都有一个静态From
方法:
public class Address
{
public string Name { get; set; }
// all the othe properties
// ....
public static Address From(Dictionary<int, JToken> answers)
{
return answers?.TryGetValue(37, out var address) ?? false
? address?.ToObject<Address>()
: null;
}
}
// so you can just write:
var address = Address.From(answers);
注意,记住Json.Net的默认反序列化设置是不区分大小写的,因此可以将name
属性从JSON反序列化为POCOs上更常用的Name
属性。
发布于 2019-06-26 08:34:29
您有几个选项:
System.Web
包(根据this answer )或JSON.Net
包(根据this answer )将其反序列化为System.Web
对象,然后使用条件检查/ null propagation operator访问property.使用方法2和3,您可以在POCO上编写一个更好的帮助器方法,它检查对象的属性并返回一个结果,该结果将是设置的类型(我建议返回一个Enum),例如:
public PropertyTypeEnum GetPropertyType(MyPocoClass myPocoClass)
{
if (myPocoClass.PropertyOne != null)
{
return PropertyTypeEnum.TypeOne;
}
else if (...)
{
return PropertyTypeEnum.TypeN
}
else
{
// probably throw a NotImplementedException here depending on your requirements
}
}
然后,在要使用该对象的代码中,可以使用返回的Enum来打开代码的逻辑路径。
https://stackoverflow.com/questions/56763348
复制相似问题