简体   繁体   English

C# 使用反射将特定属性序列化为 JSON?

[英]C# Serialize a specific property as JSON by using Reflection?

I'm a new guy on the way to learn reflection.我是一个正在学习反思的新人。 My effort is to build a serialization for a specific property in a class, for example:我的工作是为 class 中的特定属性构建序列化,例如:

public class People
{
    public Name Name { get; set; }
    public int Age { get; set; }
    public Address Address { get; set; }
}

public class Name
{
    public string First { get; set; }
    public string Last { get; set; }
}

public class Address
{
    public City City { get; set; }
    public string Street { get; set; }
}

public class City
{
    public string Country { get; set; }
    public string ZipCode { get; set; }
}

Usage:用法:

var manObj = new People
{
    Name = new Name
    {
        First = "Viet",
        Last = "Vo"
    },
    Address = new Address
    {
        City = new City
        {
            Name = "New York",
            ZipCode = "12345"
        },
        Street = "123 Street"
    },
    Age = 20
};

I would like to have a method to get a specific property and serialize it as JSON string:我想要一种方法来获取特定属性并将其序列化为 JSON 字符串:

string firstNameJson = SerializeSpecificProperty(manObj, "Name.First");
string cityZipCodeJson = SerializeSpecificProperty(manObj, "Address.City.ZipCode");

Output as JSON string format: Output 为 JSON 字符串格式:

// first name
{
    Name: {
        First: "Viet"
    }
}

// zip code
{
    Address: {
        City: {
            ZipCode: "12345"
        }
    }
}

I can loop through the class properties, but still can't find the best way to archive that.我可以遍历 class 属性,但仍然找不到存档的最佳方法。 Thanks.谢谢。

Try with Custom Attribute and Extension Method, A sample code below尝试使用自定义属性和扩展方法,下面的示例代码

Custom Attribute自定义属性

[AttributeUsage(AttributeTargets.Property,AllowMultiple = false)]
public class ConvertToJsonAttribute:Attribute
{
}

ObjectExtension对象扩展

public static class ObjectExtension
{
    public static IEnumerable<string> GetSpecificPropertyJson(this object @this)
    {
        var properties = @this.GetType().GetProperties().Where(x => x.GetCustomAttributes().OfType<ConvertToJsonAttribute>().Any());

        if (properties != null && properties.Count() > 0)
        {
            foreach (var prop in properties)
            {
                var propertyVal = prop.GetValue(@this);
                yield return JsonConvert.SerializeObject(propertyVal);
            } 
        }
       yield return null;
    }
}

Your People (Other Class declarations skipped)你的人(跳过其他 Class 声明)

public class People
{
    [ConvertToJson]
    public Name Name { get; set; }
    [ConvertToJson]
    public int Age { get; set; }
    [ConvertToJson]
    public Address Address { get; set; }

    public string DontConvertToJson { get; set; }
}

Usage (skip object initialization for simplify )用法(跳过 object 初始化以简化)

foreach (var item in manObj.GetSpecificPropertyJson())
{
    Console.WriteLine(item);
}

输出

you may try with JObject.FromObject and JObject.SelectToken search.您可以尝试使用JObject.FromObjectJObject.SelectToken搜索。

The idea is to get JObject from class instance you have and then use filter string to get a node.想法是从您拥有的 class 实例中获取JObject ,然后使用过滤器字符串获取节点。

Found property may be used to get parent up to the root and create hierarchy JObject chain like below Found 属性可用于获取父级到根并创建层次结构JObject链,如下所示

[Test]
[TestCase("Name.First")]
[TestCase("Address.City.ZipCode")]
[TestCase("Address.City.abracadabra")]
public void object2json(string path)
{
    var res = JObject.FromObject(
        new { 
        Name = new { First = "f", Last = "l" }, 
        Address = new { City = new { Name = "cn", ZipCode = "zc" }, Street = "str" }, 
        Age = 22 }
    );

    var o = JObject.FromObject(res);
    var t = o.SelectToken(path);
    if (t != null)
    {
        var jp = TraverseUp(t.Parent);

        Console.WriteLine(jp.ToString());
    }
}

JContainer TraverseUp(JContainer child)
{
    var res = child;

    while (child != null)
    {
        var pp = child.Parent?.Parent as JProperty;
        if (pp == null)
            break;
        res = new JProperty(pp.Name, new JObject(res));

        child = child.Parent?.Parent;
    }

    return res;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM