GVKun编程网logo

c# – 使用带有JSON.Net的自定义反序列化器反序列化JSON(c# json反序列化null值处理)

16

如果您对c#–使用带有JSON.Net的自定义反序列化器反序列化JSON和c#json反序列化null值处理感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解c#–使用带有JSON.Net的自定义

如果您对c# – 使用带有JSON.Net的自定义反序列化器反序列化JSONc# json反序列化null值处理感兴趣,那么这篇文章一定是您不可错过的。我们将详细讲解c# – 使用带有JSON.Net的自定义反序列化器反序列化JSON的各种细节,并对c# json反序列化null值处理进行深入的分析,此外还有关于.NET 4是否具有内置的JSON序列化器/反序列化器?、.Net使用Newtonsoft.Json.dll(JSON.NET)对象序列化成json、反序列化json示例教程、@JsonCreator 自定义反序列化函数 - JSON 框架 Jackson 精解第 5 篇、c# – 用Json.Net反序列化,将子对象反序列化为字符串/类似的持有json?的实用技巧。

本文目录一览:

c# – 使用带有JSON.Net的自定义反序列化器反序列化JSON(c# json反序列化null值处理)

c# – 使用带有JSON.Net的自定义反序列化器反序列化JSON(c# json反序列化null值处理)

我有这样的 JSON:
{
  "MobileSiteContents": {
    "au/en": [
      "http://www.url1.com","http://www.url2.com",],"cn/zh": [
      "http://www.url2643.com",]
  }
}

我正在尝试将其反序列化为IEnumerable类,如下所示:

public class MobileSiteContentsContentSectionItem : ContentSectionItem
{
    public string[] Urls { get; set; }
}

public abstract class ContentSectionItem
{
    public string Culture { get; set; }
}

那可能吗?
我意识到我可能需要为此使用Custom JsonConverter,但找不到任何示例.

我开始编写一个使用JObject.Parse进行转换的方法,但不确定这是否是正确/最有效的路径:

public IEnumerable<MobileSiteContentsContentSectionItem> Parse(string json)
{
    var jobject = JObject.Parse(json);

    var result = new List<MobileSiteContentsContentSectionItem>();

    foreach (var item in jobject.Children())
    {
        var culture = item.Path;
        string[] urls = new[] { "" }; //= this is the part I'm having troble with here...

        result.Add(new MobileSiteContentsContentSectionItem { Culture = culture,Urls = urls });
    }

    return result;
}

解决方法

你走在正确的轨道上.以下是您需要进行的更正:

>您正在迭代顶层对象的子节点,期望获得实际位于对象中的数据更低一级.您需要导航到MobileSiteContents属性的值并迭代它的子项.
>当您使用JObject的Children()时,使用允许您将它们转换为JProperty对象的重载;这将使您更容易提取所需的数据.
>从JProperty项目的名称中获取文化
>要获取网址,请获取JProperty项的值,并使用ToObject< string []>()将其转换为字符串数组.

这是更正后的代码:

public IEnumerable<MobileSiteContentsContentSectionItem> Parse(string json)
{
    var jObject = JObject.Parse(json);

    var result = new List<MobileSiteContentsContentSectionItem>();

    foreach (var item in jObject["MobileSiteContents"].Children<JProperty>())
    {
        var culture = item.Name;
        string[] urls = item.Value.ToObject<string[]>();

        result.Add(new MobileSiteContentsContentSectionItem { Culture = culture,Urls = urls });
    }

    return result;
}

如果您喜欢简洁的代码,可以将其减少为“单行”:

public IEnumerable<MobileSiteContentsContentSectionItem> Parse(string json)
{
    return JObject.Parse(json)["MobileSiteContents"]
        .Children<JProperty>()
        .Select(prop => new MobileSiteContentsContentSectionItem
        {
            Culture = prop.Name,Urls = prop.Value.ToObject<string[]>()
        })
        .ToList();
}

演示:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        {
            ""MobileSiteContents"": {
                ""au/en"": [
                    ""http://www.url1.com"",""http://www.url2.com"",""cn/zh"": [
                    ""http://www.url2643.com"",]
            }
        }";

        foreach (MobileSiteContentsContentSectionItem item in Parse(json))
        {
            Console.WriteLine(item.Culture);
            foreach (string url in item.Urls)
            {
                Console.WriteLine("  " + url);
            }
        }
    }

    public static IEnumerable<MobileSiteContentsContentSectionItem> Parse(string json)
    {
        return JObject.Parse(json)["MobileSiteContents"]
            .Children<JProperty>()
            .Select(prop => new MobileSiteContentsContentSectionItem()
            {
                Culture = prop.Name,Urls = prop.Value.ToObject<string[]>()
            })
            .ToList();
    }

    public class MobileSiteContentsContentSectionItem : ContentSectionItem
    {
        public string[] Urls { get; set; }
    }

    public abstract class ContentSectionItem
    {
        public string Culture { get; set; }
    }
}

输出:

au/en
  http://www.url1.com
  http://www.url2.com
cn/zh
  http://www.url2643.com

.NET 4是否具有内置的JSON序列化器/反序列化器?

.NET 4是否具有内置的JSON序列化器/反序列化器?

.NET 4是否附带任何可对JSON数据进行序列化/反序列化的类?

  • 我知道有第三方库,例如JSON.NET,但是我正在寻找内置在.NET中的东西。

  • 我在MSDN上找到了数据合同,但是它是用于WCF的,而不是Winforms或WPF的。

答案1

小编典典

您可以在任何需要的地方使用DataContractJsonSerializer类,它只是一个.net类,不仅限于WCF。有关如何在此处和此处使用它的更多信息。

.Net使用Newtonsoft.Json.dll(JSON.NET)对象序列化成json、反序列化json示例教程

.Net使用Newtonsoft.Json.dll(JSON.NET)对象序列化成json、反序列化json示例教程

JSON作为一种轻量级的数据交换格式,简单灵活,被很多系统用来数据交互,作为一名.NET开发人员,JSON.NET无疑是最好的序列化框架,支持XML和JSON序列化,高性能,免费开源,支持LINQ查询。目前已被微软集成于webapi框架之中,因此,熟练掌握JSON.NET相当重要,这篇文章是零度参考官网整理的示例,通过这些示例,可以全面了解JSON.NET提供的功能。

Newtonsoft.Json的地址:

官网:http://json.codeplex.com/

源码地址:https://github.com/JamesNK/Newtonsoft.Json

Newtonsoft.Json.dll下载:https://github.com/JamesNK/Newtonsoft.Json/releases

1、使用Newtonsoft.Json(JSON.NET)序列化对象,通过Newtonsoft.Json.Formatting将json格式化输出。

            Account account = new Account
            {
                Email = "1930906722@qq.com",Active = true,CreatedDate =DateTime.Now,Roles = new List<string> { "User","Admin" }
            };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(account,Newtonsoft.Json.Formatting.Indented);
            Console.WriteLine(json);
    public class Account
    {
        public string Name { get; set; }
        public string Email { get; set; }
        public bool Active { get; set; }
        public DateTime CreatedDate { get; set; }
        public IList<string> Roles { get; set; }
    }

执行结果:

2、使用Newtonsoft.Json(JSON.NET)序列化List集合:

            List<string> videogames = new List<string> { "HTML5","JavaScript",".net","c#",".net core" };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(videogames);
            Console.WriteLine(json);

执行结果:

3、使用Newtonsoft.Json(JSON.NET)序列化dictionary字典

            System.Collections.Generic.Dictionary<string,string> dic = new System.Collections.Generic.Dictionary<string,string>
            {
                { "Name","张三" },{ "Age","20" },{ "Email","193090622@qq.com" }
            };
            string json1 = Newtonsoft.Json.JsonConvert.SerializeObject(dic,Newtonsoft.Json.Formatting.Indented);
            Console.WriteLine(json1);
            Console.WriteLine("");
            Console.WriteLine("未格式化的json:");
            string json2 = Newtonsoft.Json.JsonConvert.SerializeObject(dic,Newtonsoft.Json.Formatting.None);
            Console.WriteLine(json2);

执行结果:

4、Newtonsoft.Json(JSON.NET)将序列化结果保存到指定的文件:

            User movie = new User { Name = "张三",Age = 1993 };
            using (System.IO.StreamWriter file = System.IO.File.CreateText(@"F:\UserInfo.txt"))
            {
                Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer();
                serializer.Serialize(file,movie);
            }
    public class User
    {
        public string Name { set; get; }
        public int Age { set; get; }
    }

执行后保存到文件的结果:

5、Newtonsoft.Json(JSON.NET)基于枚举类型的JsonConverters转换器

            List<JosnEnum> list = new List<JosnEnum> { JosnEnum.NotStartus,JosnEnum.Startus };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(list);
            Console.WriteLine(json);
            Console.WriteLine("");

            System.Collections.Generic.Dictionary<string,int> dic = new System.Collections.Generic.Dictionary<string,int>
            { 
            {((JosnEnum)(int)JosnEnum.NotStartus).ToString(),(int)JosnEnum.NotStartus},{((JosnEnum)(int)JosnEnum.Startus).ToString(),(int)JosnEnum.Startus}
            };
            string dicJson = Newtonsoft.Json.JsonConvert.SerializeObject(dic);
            Console.WriteLine(dicJson);

            Console.WriteLine("");
            List<JosnEnum> list2 = new List<JosnEnum>
            {
                JosnEnum.NotStartus,JosnEnum.Startus
            };
            string json3 = Newtonsoft.Json.JsonConvert.SerializeObject(list2,new Newtonsoft.Json.Converters.StringEnumConverter());
            Console.WriteLine(json3);

            Console.WriteLine("");

            List<JosnEnum> result = Newtonsoft.Json.JsonConvert.DeserializeObject<List<JosnEnum>>(json3,new Newtonsoft.Json.Converters.StringEnumConverter());
            Console.WriteLine(string.Join(",",result.Select(c => c.ToString())));
    public enum JosnEnum
    {
        NotStartus = 0,Startus = 1
    }

执行结果:

6、Newtonsoft.Json(JSON.NET)通过JRaw将JS函数序列化到JSON中

            JavaScriptSettings settings = new JavaScriptSettings
            {
                OnLoadFunction = new Newtonsoft.Json.Linq.JRaw("OnLoad"),OnSucceedFunction = new Newtonsoft.Json.Linq.JRaw("function(e) { alert(e); }")
            };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(settings,Newtonsoft.Json.Formatting.Indented);
            Console.WriteLine(json);
    public class JavaScriptSettings
    {
        public Newtonsoft.Json.Linq.JRaw OnLoadFunction { get; set; }
        public Newtonsoft.Json.Linq.JRaw OnSucceedFunction { get; set; }
    }

7、使用Newtonsoft.Json(JSON.NET)将json反序列化对象

  string json = @"{
   'Email': '1930906722@qq.com','Active': true,'CreatedDate': '2016-11-26 20:39','Roles': [
     'User','Admin'
]
 }";
            Account account = Newtonsoft.Json.JsonConvert.DeserializeObject<Account>(json);
            Console.WriteLine(account.Email);
    public class Account
    {
        public string Name { get; set; }
        public string Email { get; set; }
        public bool Active { get; set; }
        public DateTime CreatedDate { get; set; }
        public IList<string> Roles { get; set; }
    }

执行结果:

8、使用Newtonsoft.Json(JSON.NET)反序列化List集合:

            string json = @"['Html5','C#','.Net','.Net Core']";
            List<string> videogames = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>(json);
            Console.WriteLine(string.Join(",videogames));

执行结果:

9、使用Newtonsoft.Json(JSON.NET)反序列化dictionary字典

            string json = @"{'Name': '张三','Age': '23'}";
            var htmlAttributes = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string,string>>(json);
            Console.WriteLine(htmlAttributes["Name"]);
            Console.WriteLine(htmlAttributes["Age"]);

执行结果:

10、使用Newtonsoft.Json(JSON.NET)序列化var匿名类型,有时候,我们并不需要先定义一个类,然后new一个对象后再进行序列化,JSON.NET支持匿名类型的序列化和反序列化。

            var test1 = new { Name = "李四",Age = 26 };
            var json = Newtonsoft.Json.JsonConvert.SerializeObject(test1);
            Console.WriteLine(json);

            Console.WriteLine("");
            var test2 = new { Name = "",Age = 0 };
            string json1 = @"{'Name':'张三','Age':'25'}";
            var result = Newtonsoft.Json.JsonConvert.DeserializeAnonymousType(json1,test2);
            Console.WriteLine(result.Name);

执行结果:

11、Newtonsoft.Json(JSON.NET)用新JSON字符串填充指定对象的属性值

            Account account = new Account
            {
                Email = "1930906722@qq.com",CreatedDate = DateTime.Now,"Admin" }
            };
            string json = @"{'Active': false,'Roles': ['Expired']}";
            Newtonsoft.Json.JsonConvert.PopulateObject(json,account);
            Console.WriteLine(account.Active);
            Console.WriteLine(account.Email);
    public class Account
    {
        public string Name { get; set; }
        public string Email { get; set; }
        public bool Active { get; set; }
        public DateTime CreatedDate { get; set; }
        public IList<string> Roles { get; set; }
    }

执行结果:

12、使用Newtonsoft.Json(JSON.NET)反序列化时可指定构造函数:

首先我们定义如下的类型,我们希望JSON.NET反序列化对象时使用第2个构造函数,我们将第一个默认构造函数屏蔽,标记为私有private修饰符。第2个构造函数需要指定一个website对象作为参数,如果提供的参数为null则抛出异常:

public class Website
{
    public string Url { get; set; }
    private Website()
    {
    }
    public Website(Website website)
    {
        if (website == null) throw new ArgumentNullException("website");
        Url = website.Url;
    }
}

现在使用一般的方式反序列化一个JSON字符串。执行出现的结果:

我们发现该序列化方法抛出了异常,并没有按照我们预想的方式进行反序列化,JSON.NET提供如下的方式指定公有构造函数。

            string json = @"{'Url':'http://www.cnblogs.com/linJie1930906722/'}";
            Website website = Newtonsoft.Json.JsonConvert.DeserializeObject<Website>(json,new Newtonsoft.Json.JsonSerializerSettings
            {
                ConstructorHandling = Newtonsoft.Json.ConstructorHandling.AllowNonPublicDefaultConstructor
            });
            Console.WriteLine(website.Url);

执行结果:

另外,JSON.NET提供了指定任何构造函数的JsonConstructorAttribute特性,只需要在构造函数上标记,即可指定构造函数。

    public class Users
    {
        public string UserName { get; private set; }
        public bool Enabled { get; private set; }
        public Users()
        {
        }
        [Newtonsoft.Json.JsonConstructor]
        public Users(string userName,bool enabled)
        {
            UserName = userName;
            Enabled = enabled;
        }
    }
            string json = @"{""UserName"": ""希特勒"",""Enabled"": true}";
            Users user = Newtonsoft.Json.JsonConvert.DeserializeObject<Users>(json);
            Console.WriteLine(user.UserName);

执行结果:

13、当对象的属性为默认值(0或null)时不序列化该属性

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Person Partner { get; set; }
        public decimal? Salary { get; set; }
    }
            Person person1 = new Person();
            string json1 = Newtonsoft.Json.JsonConvert.SerializeObject(person1,Newtonsoft.Json.Formatting.Indented,new Newtonsoft.Json.JsonSerializerSettings
            {
                DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore
            });
            Console.WriteLine(json1);

            Console.WriteLine("");
            Person person2 = new Person(){Name = "奥巴马"};
            string json2 = Newtonsoft.Json.JsonConvert.SerializeObject(person2,new Newtonsoft.Json.JsonSerializerSettings
            {
                DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore
            });
            Console.WriteLine(json2);

执行结果:

14、Newtonsoft.Json(JSON.NET)中忽略null值得处理器

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Person Partner { get; set; }
        public decimal? Salary { get; set; }
    }
            Person person = new Person { Name = "张三",Age = 46 };
            string jsonIncludeNullValues = Newtonsoft.Json.JsonConvert.SerializeObject(person,Newtonsoft.Json.Formatting.Indented);
            Console.WriteLine(jsonIncludeNullValues);
            Console.WriteLine("");
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(person,new Newtonsoft.Json.JsonSerializerSettings
            {
                NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore
            });
            Console.WriteLine(json);

执行结果:

15、JSON.NET中循环引用的处理方法

            Employee employee1 = new Employee { Name = "张三" };
            Employee employee2 = new Employee { Name = "李四" };
            employee1.Manager = employee2;
            employee2.Manager = employee2;
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(employee1,new Newtonsoft.Json.JsonSerializerSettings
            {
                ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
            });
            Console.WriteLine(json);
    public class Employee
    {
        public string Name { get; set; }
        public Employee Manager { get; set; }
    }

执行结果:

16、通过ContractResolver指定属性名首字母小写,通常,在.NET中属性采用PascalCase规则(首字母大写),在JavaScript中属性名使用CamelCase规则(首字母小写),我们希望序列化后的JSON字符串符合CamelCase规则,JSON.NET提供的ContractResolver可以设置属性名小写序列化

    public class User
    {
        public string Name { set; get; }
        public int Age { set; get; }
    }
            User person = new User { Name = "张三",Age =52 };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(person,new Newtonsoft.Json.JsonSerializerSettings
            {
                ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
            });
            Console.WriteLine(json);

执行结果:

17、JSON.NET中通过特性序列化枚举类型

    public enum ProductStatus
    { 
        NotConfirmed,Active,Deleted
    }

    public class Product
    {
        public string Name { get; set; }

        [Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
        public ProductStatus Status { get; set; }
    }
            Product user = new Product { Name = @"羽绒服",Status = ProductStatus.Deleted };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(user,Newtonsoft.Json.Formatting.Indented);
            Console.WriteLine(json);

执行结果:

18、指定需要序列化的属性

    [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
    public class Categroy
    {
        //Id不需要序列化
        public Guid Id { get; set; }

        [Newtonsoft.Json.JsonProperty]
        public string Name { get; set; }

        [Newtonsoft.Json.JsonProperty]
        public int Size { get; set; }
    }
            Categroy categroy = new Categroy
            {
                Id = Guid.NewGuid(),Name = "内衣",Size = 52
            };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(categroy,Newtonsoft.Json.Formatting.Indented);
            Console.WriteLine(json);

执行结果:

19、序列化对象时指定属性名

    public class Videogame
    {
        [Newtonsoft.Json.JsonProperty("name")]
        public string Name { get; set; }

        [Newtonsoft.Json.JsonProperty("release_date")]
        public DateTime ReleaseDate { get; set; }
    }
            Videogame starcraft = new Videogame
            {
                Name = "英雄联盟",ReleaseDate = DateTime.Now
            };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(starcraft,Newtonsoft.Json.Formatting.Indented);
            Console.WriteLine(json);

执行结果:

20、序列化时指定属性在JSON中的顺序

    public class Personl
    {
        [Newtonsoft.Json.JsonProperty(Order = 2)]
        public string FirstName { get; set; }

        [Newtonsoft.Json.JsonProperty(Order = 1)]
        public string LastName { get; set; }
    }
            Personl person = new Personl { FirstName = "张三",LastName = "李四" };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(person,Newtonsoft.Json.Formatting.Indented);
            Console.WriteLine(json);

执行结果:

21、反序列化指定属性是否必须有值必须不为null,在反序列化一个JSON时,可通过JsonProperty特性的required指定反序列化行为,当反序列化行为与指定的行为不匹配时,JSON.NET将抛出异常,required是枚举,required.Always表示属性必须有值切不能为null,required.AllowNull表示属性必须有值,但允许为null值。

    public class Order
    {
        [Newtonsoft.Json.JsonProperty(required = Newtonsoft.Json.required.Always)]
        public string Name { get; set; }

        [Newtonsoft.Json.JsonProperty(required = Newtonsoft.Json.required.AllowNull)]
        public DateTime? ReleaseDate { get; set; }
    }
            string json = @"{
    'Name': '促销订单','ReleaseDate': null
  }";
            Order order = Newtonsoft.Json.JsonConvert.DeserializeObject<Order>(json);
            Console.WriteLine(order.Name);
            Console.WriteLine(order.ReleaseDate);

执行结果:

22、通过特性指定null值忽略序列化

    public class Vessel
    {
        public string Name { get; set; }

        [Newtonsoft.Json.JsonProperty(NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
        public DateTime? launchdate { get; set; }
    }
            Vessel vessel = new Vessel { Name = "张三" };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(vessel,Newtonsoft.Json.Formatting.Indented);
            Console.WriteLine(json);

执行结果:

23、忽略不需要序列化的属性,并不是对象所有属性都要参与序列化,我们可以使用JsonIgnore特性排除不需要序列化的属性,下面示例中的PasswordHash将被忽略。

    public class Accounts
    {
        public string FullName { get; set; }
        public string EmailAddress { get; set; }
        [Newtonsoft.Json.JsonIgnore]
        public string PasswordHash { get; set; }
    }
            Accounts account = new Accounts
            {
                FullName = "admin",EmailAddress = "1930906722@qq.com",PasswordHash = "dfsfgerhtyhsasdhjyujtgwe454811sfsg8d"
            };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(account);
            Console.WriteLine(json);

执行结果:

24、序列化或反序列化时指定日期时间格式,JSON.NET中提供一个名为JsonSerializerSettings的设置对象,可通过此对象设置很多序列化和反序列化的行为,如果要设置JSON.NET序列化输出的日期时间格式,只需要指定格式化字符串即可。通过JsonSerializerSettings的DateFormatString属性指定日期时间格式:

    public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime CreateDate { get; set; }
    }
            Customer custom = new Customer { FirstName = "张三",LastName = "李四",CreateDate = DateTime.Now };
            Newtonsoft.Json.JsonSerializerSettings settings = new Newtonsoft.Json.JsonSerializerSettings
            {
                DateFormatString = "yyyy-MM-dd HH:mm:ss",Formatting = Newtonsoft.Json.Formatting.Indented
            };
            string json = Newtonsoft.Json.JsonConvert.SerializeObject(custom,settings);
            Console.WriteLine(json);

执行结果:

@JsonCreator 自定义反序列化函数 - JSON 框架 Jackson 精解第 5 篇

@JsonCreator 自定义反序列化函数 - JSON 框架 Jackson 精解第 5 篇

高春辉、王春生、朱峰:关于开源创业的 15 件小事

转:

@JsonCreator 自定义反序列化函数 - JSON 框架 Jackson 精解第 5 篇

@JsonCreator自定义反序列化函数-JSON框架Jackson精解第5篇

Jackson 是 Spring Boot (SpringBoot) 默认的 JSON 数据处理框架,但是其并不依赖于任何的 Spring 库。有的小伙伴以为 Jackson 只能在 Spring 框架内使用,其实不是的,没有这种限制。它提供了很多的 JSON 数据处理方法、注解,也包括流式 API、树模型、数据绑定,以及复杂数据类型转换等功能。它虽然简单易用,但绝对不是小玩具,更多的内容我会写成一个系列,5-10 篇文章,请您继续关注我。

  • 《序列化与反序列化核心用法 - JSON 框架 Jackson 精解第 1 篇》
  • 《特殊数据格式处理 - JSON 框架 Jackson 精解第 2 篇》
  • 《属性序列化自定义排序与字母表排序 - JSON 框架 Jackson 精解第 3 篇》
  • 《@JacksonInject 与 @JsonAlias 注解 - JSON 框架 Jackson 精解第 4 篇》

本节继续为大家介绍在 JSON 反序列化过程中,如何使用 @JsonCreator 注解和 @ConstructorProperties 注解自定义反序列化函数。

一、Jackson 反序列化过程做了什么?

对于 Jackson 的 JSON 数据格式,反序列化过程就是将 JSON 字符串反序列化为 java 对象

ObjectMapper mapper = new ObjectMapper();

//将JSON字符串反序列化为java对象
String jsonInString = "{"name":"乔丹","age":45,"hobbies":["高尔夫球","棒球"]}";
PlayerStar3 jordan = mapper.readValue(jsonInString, PlayerStar3.class);

System.out.println(jordan);

默认情况下,Jackson 在反序列化过程中调用了哪些函数,给大家介绍一下

  • 首先调用反序列化的目标类 PlayerStar3 的无参构造函数,构造一个 java 对象
  • 然后调用该类的成员变量的 set 方法,为该对象的每一个成员变量赋值。

所以默认情况下,一个 Java 类使用 Jackson 做反序列化,必须有 public 无参构造函数 (java 中不写也默认有),必须有成员变量的 set 方法。

二、@JsonCreator 注解

默认情况下,Jackson 的反序列化过程是上面描述的那样,使用无参构造函数及 set 方法。除此之外,我们还可以使用 @JsonCreator 注解自定义反序列化的过程,在我们自定义的反序列化函数里面,我们有更强的灵活性,可以完成更多的非规定动作。一共有两种自定义反序列化渠道:

  • @JsonCreator 注解加在构造方法上
  • @JsonCreator 注解加在工厂静态方法上

使用了 @JsonCreator 注解之后,将使用该注解标注的方法进行反序列化对象的构造,默认的使用无参构造函数及 set 方法进行反序列化的过程失效。

2.1.@JsonCreator 注解加在构造方法上

该 PlayerStar3 对应的 JSON 字符串是第一小节中的 jsonInString。下文的构造函数,你希望将哪些属性值赋值给 java 对象的成员变量,你就使用 @JsonProperty("salary") 去定义它。

public class PlayerStar3 {

  private String name;
  private Integer age;
  private String[] hobbies;    //业余爱好,数组
  private List
  
  
   
    friends;   //  朋友
  private Map
   
   
    
     salary; //年收入 Map

  //这段是我们的核心代码,使用JsonCreator注解说明该方法是反序列化构造方法。
  @JsonCreator
  public PlayerStar3(@JsonProperty("name") String name,
                     @JsonProperty("age") Integer age,
                     @JsonProperty("hobbies") String[] hobbies,
                     @JsonProperty("friends") List
    
    
     
      friends,
                     @JsonProperty("salary") Map
     
     
      
       salary) {
    this.name = name;
    this.age = age;
    this.hobbies = hobbies;
    this.friends = friends;
    this.salary = salary;
  }

  //这里省略一个toString()方法
}

     
     
    
    
   
   
  
  

我们使用第一小节中的反序列化代码,将 jsonInString 反序列化构造 PlayerStar3 对象,控制台输出结果如下 (对象的 toString () 方法输出):

PlayerStar3{name=''乔丹'', age=45, hobbies=[高尔夫球, 棒球], friends=null, salary=null}

@JsonCreator 标注的构造方法里面下断点,也的确证明在 java 对象反序列化构造的过程中使用的是该方法。

2.2.@JsonCreator 注解加在工厂静态方法上

除了可以将 @JsonCreator 加在构造方法上,还可以使用静态工厂函数反序列化构造 java 对象。使用方法如下:

public class PlayerStar3 {

  //  省略若干成员变量的定义,和上文一样

  @JsonCreator
  public static PlayerStar3 createPlayer(@JsonProperty("name") String name,
                                         @JsonProperty("age") Integer age,
                                         @JsonProperty("hobbies") String[] hobbies,
                                         @JsonProperty("friends") List
  
  
   
    friends,
                                         @JsonProperty("salary") Map
   
   
    
     salary) {
    PlayerStar3 player = new PlayerStar3();  //new 一个java对象
    player.name = name;    //赋值
    player.age = age;
    player.hobbies = hobbies;
    player.friends = friends;
    player.salary = salary;
    return player;
  }
    //这里省略一个toString()方法
}

   
   
  
  

使用 @JsonCreator 注解加在工厂静态方法上,可以达到一样的反序列化效果。

三、@ConstructorProperties 注解

@ConstructorProperties 注解的作用和 @JsonCreator 注解起到的作用是一致的,但是它只能加在构造方法上,作为反序列化函数。但是它的语法更简洁,使用起来也更加方便,不用 @JsonProperty 注解。又提供了灵活性,我们可以在构造方法反序列化过程中,针对该对象做更多的非规定操作。

@ConstructorProperties({"name", "age","hobbies", "friends","salary"})
public PlayerStar3(String name,
                   Integer age,
                   String[] hobbies,
                   List
  
  
   
    friends,
                   Map
   
   
    
     salary) {
  this.name = name;
  this.age = age;
  this.hobbies = hobbies;
  this.friends = friends;
  this.salary = salary;
}

   
   
  
  

使用 @ConstructorProperties 注解加在构造方法上,可以达到一样的反序列化效果。

欢迎关注我的博客,里面有很多精品合集

  • 本文转载注明出处(必须带连接,不能只转文字):字母哥博客。

觉得对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创作动力! 。另外,笔者最近一段时间输出了如下的精品内容,期待您的关注。

  • 《手摸手教你学 Spring Boot2.0》
  • 《Spring Security-JWT-OAuth2 一本通》
  • 《实战前后端分离 RBAC 权限管理系统》
  • 《实战 SpringCloud 微服务从青铜到王者》
  • 《VUE 深入浅出系列》

转:

@JsonCreator 自定义反序列化函数 - JSON 框架 Jackson 精解第 5 篇


--Posted from Rpc

c# – 用Json.Net反序列化,将子对象反序列化为字符串/类似的持有json?

c# – 用Json.Net反序列化,将子对象反序列化为字符串/类似的持有json?

我正在尝试使用Json创建配置文件,该文件将保存各种类型对象的配置.

考虑这个文件:

{
    "cameras": [
        {
            "type": "Some.Namespace.CameraClass","assembly": "Some.Assembly","configuration": {
                "ip": "127.0.0.1","port": 8080
            }
        }
    ]
}

在运行时,我将使用两个“类型”和“程序集”属性来构造支持特定接口的对象,然后我想将配置加载到该对象中.

但是,在编译时我不知道“配置”将映射到的类型.我想将它保留为json“属性”并将其提供给相机对象,然后让该对象将json反序列化为正确的类型.

因此,我想将包含特定相机类型配置的配置文件的一部分“随身携带”到对象本身,然后让它处理它,像我一样把它当作黑盒子处理它.应该保留该部分的结构,因为在为每个摄像机实现创建配置类型时我想要完全保真,甚至在必要时添加子对象.

对于这个特定的相机,我会配置一个IP地址和一个端口,对于其他一些相机我需要授权数据,而对于其他一些相机则完全不同.

我希望保持这种配置的属性能够直接获取Json,仍然是一个字符串.

这可能吗?

这是一个有一些位注释掉的LINQPad示例:

void Main()
{
    const string configurationFile = @"[
    {
        ""type"": ""UserQuery+Camera1"",""configuration"": { ""id"": 10 }
    },{
        ""type"": ""UserQuery+Camera2"",""configuration"": { ""name"": ""The second camera"" }
    }
]";
    var cameras = JsonConvert.DeserializeObject<Camera[]>(configurationFile);
    foreach (var camera in cameras)
    {
        var type = Type.GetType(camera.Type);
        var instance = Activator.CreateInstance(type,new object[0]) as ICamera;
        // instance.Configure(camera.Configuration);
    }
}

public class Camera
{
    public string Type { get; set; }
    public JObject Configuration { get; set; }
}

public interface ICamera
{
    void Configure(string json);
}

public class Camera1 : ICamera
{
    private class Configuration
    {
        public int Id { get; set; }
    }

    public void Configure(string json)
    {
        JsonConvert.DeserializeObject<Configuration>(json).Dump();
    }
}

public class Camera2 : ICamera
{
    private class Configuration
    {
        public string Name { get; set; }
    }

    public void Configure(string json)
    {
        JsonConvert.DeserializeObject<Configuration>(json).Dump();
    }
}

两个注释掉的位,即Camera类中的属性,以及对Configure方法的调用,都是我想要的.

有什么东西我可以标记该属性,或者我可以为该属性选择的其他类型,这将使​​这工作吗?

我知道我可以使属性动态化,这会将JObject填入其中,但是每个相机实现的每个Configure方法都必须处理JObject而不是已知的非动态类型.

解决方法

看起来如果你使用JObject类型的属性,它会解析但保留JSON:
using System;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;    

public class Foo
{
    public string Name { get; set; }
    public int Age { get; set; }
    public JObject Configuration { get; set; }
}

public class Test
{
   public static void Main()
   {
       var json = File.ReadAllText("test.json");
       var foo = JsonConvert.DeserializeObject<Foo>(json);
       Console.WriteLine(foo.Configuration);
   }

}

Test.json:

{
  "name": "Jon","age": 10,"configuration": {
    "ip": "127.0.0.1","port": 8080
  }
}

输出:

{
  "ip": "127.0.0.1","port": 8080
}

我怀疑你可以直接从JObject反序列化,但如果你真的想,你总是可以将它转换回字符串.

今天关于c# – 使用带有JSON.Net的自定义反序列化器反序列化JSONc# json反序列化null值处理的介绍到此结束,谢谢您的阅读,有关.NET 4是否具有内置的JSON序列化器/反序列化器?、.Net使用Newtonsoft.Json.dll(JSON.NET)对象序列化成json、反序列化json示例教程、@JsonCreator 自定义反序列化函数 - JSON 框架 Jackson 精解第 5 篇、c# – 用Json.Net反序列化,将子对象反序列化为字符串/类似的持有json?等更多相关知识的信息可以在本站进行查询。

本文标签: