编辑:我想我应该提到我无法控制JSON,而且我知道通常我的C#对象应该与JSON匹配。我的问题不是“为什么不反序列化?”。我知道为什么不是这样。我在问是否有一种方法可以按照我的要求反序列化JSON。
我正在使用Newtonsoft.Json。
我有一个包含1个对象的JSON字符串。我需要将该对象反序列化为带有嵌套对象的C#对象。
所以可以说我的JSON看起来像这样。
pick_car = raw_input("So whats your favourite car brand then?").lower()
for brand_name in cars:
if brand_name in pick_car:
print 'okay so you like ' + brand_name
这是我的C#对象
{
"id": 123,
"userName": "fflintstone",
"address": "345 Cave Stone Road",
"address2": "",
"city": "Bedrock",
"state": "AZ",
"zip": "",
}
AddressModel地址属性是一个嵌套对象。该对象包含实际的地址属性。因此,我需要反序列化JSON对象,以便将id和userName添加到Customer对象,然后将地址字段添加到嵌套的Address对象。
我还无法找到newtonsoft内置的方法来完成此任务。有什么想法吗?
答案 0 :(得分:3)
如果您是设置将要由代码使用的JSON的人,则您的JSON未设置为与对象匹配。
它应该像这样:
{
"id": 123,
"userName": "fflintstone",
"address": {
// address properties here
}
}
否则,您需要更新C#对象以匹配JSON,这将意味着JSON中每个项目的单独属性:
public class Customer
{
public long Id { get; set; }
public string UserName { get; set; }
public string Address { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZIP { get; set; }
}
此外,如果您同时设置了这两个名称,则可能不应将街道名称命名为“地址”。对我来说,“地址”一词指的是街道名称,号码,城市,州和邮政编码。
如果您无法控制JSON,则没有真正的方法使用Json.Net之类的方法将JSON完全反序列化为对象。您需要设置某种映射器,或直接查找属性以获得其值,以将其添加到对象中。您可以将JSON解析为JObject,然后访问所需的属性。
JObject foo = JObject.Parse(//your JSON string here);
customer.Address = (string)foo["Address"];
customer.Address2 = (string)foo["Address2];
通常,如果您不是JSON结构的控制者,那么最好使您的对象与您获得的JSON匹配。
答案 1 :(得分:2)
您可以使用自定义JsonConverter进行此操作。
public class CustomerJsonConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is Customer customer)
{
var token = new JObject
{
["id"] = customer.Id,
["userName"] = customer.UserName,
["address"] = customer.Address.Address,
["address2"] = customer.Address.Address2,
["city"] = customer.Address.City,
["state"] = customer.Address.State,
["zip"] = customer.Address.ZIP
};
token.WriteTo(writer);
}
else
{
throw new InvalidOperationException();
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var obj = JToken.ReadFrom(reader);
if (obj.Type != JTokenType.Object)
{
return null;
}
return new Customer
{
Id = (long) obj["id"],
UserName = (string) obj["userName"],
Address = obj.ToObject<AddressModel>()
};
}
public override bool CanRead => true;
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Customer);
}
}
在JsonConverterAttribute
类上带有Customer
。
[JsonConverter(typeof(CustomerJsonConverter))]
public class Customer
{
public long Id { get; set; }
public string UserName { get; set; }
public AddressModel Address { get; set; }
}
public class AddressModel
{
public string Address { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZIP { get; set; }
}
并这样利用:
var customer = JsonConvert.DeserializeObject<Customer>(customerJson);
或者,您可以简单地使用一个中间映射模型。
public class CustomerFlattened
{
public long Id { get; set; }
public string UserName { get; set; }
public string Address { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZIP { get; set; }
public Customer ToCustomer()
{
return new Customer
{
Id = Id,
UserName = UserName,
Address = new AddressModel
{
Address = Address,
Address2 = Address2,
City = City,
State = State,
ZIP = ZIP
}
};
}
public static CustomerFlattened FromCustomer(Customer customer)
{
return new CustomerFlattened
{
Id = customer.Id,
UserName = customer.UserName,
Address = customer.Address.Address,
Address2 = customer.Address.Address2,
City = customer.Address.City,
State = customer.Address.State,
ZIP = customer.Address.ZIP
};
}
}
并这样利用:
var customer =
JsonConvert.Deserialize<CustomerFlattened>(
jsonOriginal
)
.ToCustomer();
var customerFlattened = CustomerFlattened.FromCustomer(customer);
var jsonConverted = JsonConvert.Serialize(customerFlattened );
答案 2 :(得分:1)
如果您愿意使用其他工具,则可以创建一个与JSON匹配的DTO,然后使用诸如Automapper之类的映射器将DTO reverse flatten插入对象模型。
答案 3 :(得分:1)
由于JSON和对象模型不匹配,因此您必须反序列化为临时对象并自己映射字段。在此示例中,我将反序列化为一个用作模板的匿名对象。
schema = return visitSchema(schema, {
[VisitSchemaKind.OBJECT_TYPE](type: GraphQLObjectType) {
if (type.getFields().relatedNews) {
// console.log(type.getFields());
return new GraphQLObjectType({
name: type.name,
fields: {
...fromPairs(Object.values(type.getFields()).map(({name, type, args, resolve, description}) => [name, {type, args: {}, resolve, description}])),
relatedNews: {
type: schema.getType('NewsArticle'),
resolve(obj) {
console.log('foo');
}
}
}
});
}
return type;
},
});
输出:
WITH RawDebug AS
(
SELECT
STRUCT(DebugReason,DebugData) AS Debug
FROM `devicedata.Debug.T*`
WHERE _TABLE_SUFFIX="20180624"
),
RawGPS AS (
SELECT
STRUCT<DebugReason INT64, DebugData STRING>(NULL, NULL) AS Debug
FROM
`devicedata.Gps.T*` AS g
WHERE _TABLE_SUFFIX="20180624"
)
SELECT Debug
FROM RawDebug
UNION ALL
SELECT Debug
FROM RawGPS
答案 4 :(得分:-1)
首先对于要使用AdressModel类创建的对象,您需要更改JSON文档,我已更改为:
{ "id": 123, "userName": "fflintstone", "Address": {
"address": "345 Cave Stone Road",
"address2": "",
"city": "Bedrock",
"state": "AZ",
"zip": "" } }
然后针对模型,我创建了这两个模型:
public class Customer
{
public long id { get; set; }
public string userName { get; set; }
public AddressModel Address { get; set; }
}
public class AddressModel
{
public string address { get; set; }
public string address2 { get; set; }
public string city { get; set; }
public string state { get; set; }
public string zip { get; set; }
}
现在要反序列化Json文档,您可以执行以下操作:
Customer jsonConverted = new Customer();
using (StreamReader r = new StreamReader(HostingEnvironment.ApplicationPhysicalPath + @"\infoFile.json"))
{
var json = r.ReadToEnd();
jsonConverted = JsonConvert.DeserializeObject<Customer>(json);
}