C# 将平面JSON/字典映射到模型(包含子类)

C# 将平面JSON/字典映射到模型(包含子类),c#,json,json.net,automapper,automapper-4,C#,Json,Json.net,Automapper,Automapper 4,我想把一个平面json字符串转换成一个模型,目标类有子类,平面json有所有带有前缀的子类对象;比如“{classname}.{property}” 这是我的目的地课程: public class Person { public string FirstName { get; set; } public string LastName { get; set; } public virtual EmploymentDetails EmploymentDetails { ge

我想把一个平面json字符串转换成一个模型,目标类有子类,平面json有所有带有前缀的子类对象;比如“{classname}.{property}”

这是我的目的地课程:

public class Person {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public virtual EmploymentDetails EmploymentDetails { get;set;}
    public virtual ContactDetails ContactDetails { get;set;}
}
public class EmploymentDetails {
    public string JobTitle { get; set; }
    public DateTime StartDate { get; set; }
}
public class ContactDetails {
    public string HouseNumberName { get; set; }
    public string Road { get; set; }
}
我尝试了以下方法:

public static void main() {
    var json = @"{""FirstName"": ""Joey"",""LastName"": ""Billy"",""EmploymentDetails.JobTitle"": ""JobTitle"",""EmploymentDetails.StartDate"": ""2015-01-01T00:00:00"",""ContactDetails.HouseNumberName"": ""10"",""ContactDetails.Road"": ""Road"",}";

    //try using AutoMapper
    Mapper.CreateMap<string,Person>();
    var personModel = Mapper.Map<Person>(json);
    //just returns null values

    //try using Newtonsoft
    personModel = Newtonsoft.Json.JsonConvert.DeserializeObject<Person>(json);
    //fills values but obviously returns no nested data
}
publicstaticvoidmain(){
var json=@“{”“FirstName”“:”“Joey”“LastName”“:”“Billy”“EmploymentDetails.JobTitle”“:”“JobTitle”“EmploymentDetails.StartDate”“:”“2015-01-01T00:00:00”“ContactDetails.HouseNumberName”“:”“10”“ContactDetails.Road”“:”“Road”“,”“Road”“);
//尝试使用AutoMapper
CreateMap();
var personModel=Mapper.Map(json);
//只返回空值
//尝试使用Newtonsoft
personModel=Newtonsoft.Json.JsonConvert.DeserializeObject(Json);
//填充值,但显然不返回嵌套数据
}
我知道Automapper有RecognizePrefix和RecognizeDestinationPrefix,但是Automapper似乎只关心它是否在原始对象中,而不是子类中

我可能会将我的JSON字符串作为字典,但即使这样,我也不知道如何将其映射到具有子类的模型

人们希望我可以拥有无限多的子类,JSON字符串可以将平面JSON模型映射到一个模型。

您可以创建一个以通用方式实现这一点的模型,使用a对被反序列化的类或其包含的类中的属性进行分组和填充(视情况而定)

您没有要求序列化,只要求反序列化,所以这就是它的作用:

public class JsonFlatteningConverter : JsonConverter
{
    readonly IContractResolver resolver;

    public JsonFlatteningConverter(IContractResolver resolver)
    {
        if (resolver == null)
            throw new ArgumentNullException();
        this.resolver = resolver;
    }

    public override bool CanConvert(Type objectType)
    {
        return resolver.ResolveContract(objectType) is JsonObjectContract;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;

        JObject jObject = JObject.Load(reader);
        var contract = (JsonObjectContract)resolver.ResolveContract(objectType); // Throw an InvalidCastException if this object does not map to a JObject.

        existingValue = existingValue ?? contract.DefaultCreator();

        if (jObject.Count == 0)
            return existingValue;

        var groups = jObject.Properties().GroupBy(p => p.Name.Contains('.') ? p.Name.Split('.').FirstOrDefault() : null).ToArray();
        foreach (var group in groups)
        {
            if (string.IsNullOrEmpty(group.Key))
            {
                var subObj = new JObject(group);
                using (var subReader = subObj.CreateReader())
                    serializer.Populate(subReader, existingValue);
            }
            else
            {
                var jsonProperty = contract.Properties[group.Key];
                if (jsonProperty == null || !jsonProperty.Writable)
                    continue;
                if (jsonProperty != null)
                {
                    var subObj = new JObject(group.Select(p => new JProperty(p.Name.Substring(group.Key.Length + 1), p.Value)));
                    using (var subReader = subObj.CreateReader())
                    {
                        var propertyValue = serializer.Deserialize(subReader, jsonProperty.PropertyType);
                        jsonProperty.ValueProvider.SetValue(existingValue, propertyValue);
                    }
                }
            }
        }
        return existingValue;
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}
然后就这样使用它:

        var resolver = new DefaultContractResolver();
        var settings = new JsonSerializerSettings { ContractResolver = resolver, Converters = new JsonConverter[] { new JsonFlatteningConverter(resolver) } };

        var person = JsonConvert.DeserializeObject<Person>(json, settings);
var resolver=newdefaultContractResolver();
var settings=new JsonSerializerSettings{ContractResolver=resolver,Converters=new JsonConverter[]{new jsonFlatingConverter(resolver)};
var person=JsonConvert.DeserializeObject(json,设置);

原型。

你这个绝对的野兽!!是的,序列化是小菜一碟,我只知道有更好的方法,我也在进行JObject和reflection,但我的方法很糟糕。你也解释了更多的子类!因此,“ContactDetails.County.CountyName”或“EmploymentDetails.Employer.CompanyName”也会起作用,假设相关的类或在其中。干杯。如果能与
dynamic
一起使用,那就太好了。当前在尝试检索
jsonProperty
时引发错误,因为没有。
        var resolver = new DefaultContractResolver();
        var settings = new JsonSerializerSettings { ContractResolver = resolver, Converters = new JsonConverter[] { new JsonFlatteningConverter(resolver) } };

        var person = JsonConvert.DeserializeObject<Person>(json, settings);