欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#使用Json.Net對JSON與對象的序列化與反序列化

 更新時間:2022年05月13日 09:25:13   作者:springsnow  
這篇文章介紹了Json.Net對JSON與對象的序列化與反序列化,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

一、使用Json.Net

Json.Net是支持序列化和反序列化DataTable、DataSet、Entity Framework和Entity的。

1、把DataTable轉(zhuǎn)換成json格式,使用最新Json.Net DLL ,已經(jīng)內(nèi)置轉(zhuǎn)換器。

DataTable dt = catDAO.GetAllCategory();
string result = JsonConvert.SerializeObject(dt);

注意:Json.Net老版本轉(zhuǎn)換DataTable,需要自定義一個JavaScriptConverter派生類。

//引入命名空間 
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

void Main()
{
    //執(zhí)行轉(zhuǎn)換
    DataTable dt = catDAO.GetAllCategory();
    string result = JsonConvert.SerializeObject(dt, new DataTableConverter());
}

///
/// DataTable JSON轉(zhuǎn)換類
///
public class DataTableConverter : JavaScriptConverter
{
    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        DataTable dt = obj as DataTable; ;//將Datatable轉(zhuǎn)成Dictionary完成序列化
        Dictionary<string, object> result = new Dictionary<string, object>();
        if (dt != null)
        {
            ArrayList arrList = new ArrayList();
            foreach (DataRow dr in dt.Rows)//循環(huán)每行
            {
                Dictionary<string, object> dic = new Dictionary<string, object>();
                foreach (DataColumn dc in dt.Columns)
                {
                    dic.Add(dc.ColumnName, dr[dc.ColumnName]);//Dic中存儲列名和每列值
                }
                arrList.Add(dic);//ArrayList中保存各行信息
            }
            result[dt.TableName] = arrList; ;//表名作為Key,ArrayList作為值
        }
        return result;

    }

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        if (dictionary == null)
            throw new ArgumentNullException("dictionary");

        if (type == typeof(DataTable))
        { //將Dictionary轉(zhuǎn)成Datatable完成反序列化
            foreach (KeyValuePair<string, object> table in dictionary)
            {
                DataTable dt = new DataTable(table.Key);//表名
                ArrayList rows = (ArrayList)table.Value;
                //列名
                Dictionary<string, object> row = serializer.ConvertToType<string, object>>(rows[0]);
                foreach (string item in row.Keys)
                {
                    dt.Columns.Add(item);
                }
                //每行數(shù)據(jù)
                for (int i = 0; i < rows.Count; i++)
                {
                    DataRow dr = dt.NewRow();
                    Dictionary<string, object> dic = serializer.ConvertToType<string, object>>(rows[i]);
                    foreach (KeyValuePair<string, object> item in dic)
                    {
                        dr[item.Key] = item.Value;
                    }
                    dt.Rows.Add(dr);
                }
                return dt;
            }
        }
        return null;
    }

    ///
    /// 獲取本轉(zhuǎn)換器支持的類型
    ///
    public override IEnumerable SupportedTypes
    {
        get
        {
            return new Type[] { typeof(DataTable) };
        }
    }
}

2、對Json.Net序列化和反序列化的控制

實例化一個JsonSerializerSettings對象,并把它賦值給JsonConvert的參數(shù)即可.

var jSetting = new JsonSerializerSettings();
string json = JsonConvert.SerializeObject(obj,jSetting);

DataTable:

//序列化DataTable
DataTable dt = new DataTable();
dt.Columns.Add("Age", Type.GetType("System.Int32"));
dt.Columns.Add("Name", Type.GetType("System.String"));
dt.Columns.Add("Sex", Type.GetType("System.String"));
dt.Columns.Add("IsMarry", Type.GetType("System.Boolean"));
for (int i = 0; i < 4; i++)
{
    DataRow dr = dt.NewRow();
    dr["Age"] = i + 1;
    dr["Name"] = "Name" + i;
    dr["Sex"] = i % 2 == 0 ? "男" : "女";
    dr["IsMarry"] = i % 2 > 0 ? true : false;
    dt.Rows.Add(dr);
}
Console.WriteLine(JsonConvert.SerializeObject(dt, new JsonSerializerSettings() { Formatting = Newtonsoft.Json.Formatting.Indented }));
//[
//  {
//    "Age": 1,
//    "Name": "Name0",
//    "Sex": "男",
//    "IsMarry": false
//  },
//  {
//    "Age": 2,
//    "Name": "Name1",
//    "Sex": "女",
//    "IsMarry": true
//  },
//  {
//    "Age": 3,
//    "Name": "Name2",
//    "Sex": "男",
//    "IsMarry": false
//  },
//  {
//    "Age": 4,
//    "Name": "Name3",
//    "Sex": "女",
//    "IsMarry": true
//  }
//]

利用上面字符串進行反序列化

string json = JsonConvert.SerializeObject(dt);
dt = JsonConvert.DeserializeObject(json);
foreach (DataRow dr in dt.Rows)
{
    Console.WriteLine("{0}\t{1}\t{2}\t{3}\t", dr[0], dr[1], dr[2], dr[3]);
}


//1 Name0 男 False?
//2 Name1 女 True?
//3 Name2 男 False?
//4 Name3 女 True

二、空值的處理

這里的空值指的是引用類型為NULL時,Json.Net如何處理.通過設置jSetting.NullValueHandling的值來確定,該值為枚舉類型。

  • NullValueHandling.Ignore: 忽略為NULL的值
  • NullValueHandling.Include: 默認值,包括為NULL的值

實例:

void Main()
{
    Staff jack = new Staff { Name = "Jack", Age = 31, Gender = "Male", DepartmentName = "Personnel Department", Leader = null };
    var jSetting = new JsonSerializerSettings();
    jSetting.NullValueHandling = NullValueHandling.Ignore;
    string json = JsonConvert.SerializeObject(jack, jSetting);
    Console.WriteLine(json);
    //{"Name":"Jack","Age":31,"Gender":"Male","DepartmentName":"Personnel Department"}
}

//員工類:
public class Staff
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }
    public string DepartmentName { get; set; }
    public Staff Leader { get; set; }
}

三、默認值的處理

一般是對于值類型的處理,通過設置jSetting.DefaultValueHandling的值來確定,該值為枚舉類型.

  • DefaultValueHandling.Ignore:序列化和反序列化時,忽略默認值 
  • DefaultValueHandling.Include:序列化和反序列化時,包含默認值

給成員設置默任值,用到"DefaultValue(value)"特性,當然別忘了引入命名空間"System.ComponentModel",假設員工的年齡默認值為30。

[DefaultValue(30)]
public int Age { get; set; }

序列化時我想忽略為默認值的成員:

Staff jack = new Staff { Name = "Jack", Age = 30, Gender = "Male", DepartmentName = "Personnel Department", Leader = null };
var jSetting = new JsonSerializerSettings();
jSetting.DefaultValueHandling = DefaultValueHandling.Ignore;
string json = JsonConvert.SerializeObject(jack, jSetting);
Console.WriteLine(json);
//{"Name":"Jack","Gender":"Male","DepartmentName":"Personnel Department"}

四、忽略某些屬性

首先介紹Json.Net成員序列化的模式:OptOut 和 OptIn.

  • OptOut:默認值。類中所有公有成員會被序列化,如果不想被序列化,可以用特性JsonIgnore。
  • OptIn:在這種情況下,所有的成員不會被序列化,類中的成員只有標有特性JsonProperty的才會被序列化,當類的成員很多,但客戶端僅僅需要一部分數(shù)據(jù)時,很有用。

假如客戶僅僅需要員工的姓名,此時序列化:

void Main()
{
    Staff jack = new Staff { Name = "Jack", Age = 30, Gender = "Male", DepartmentName = "Personnel Department", Leader = null };
    string json = JsonConvert.SerializeObject(jack);
    Console.WriteLine(json);
    //{"Name":"Jack"}
}

[JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
public class Staff
{
    [JsonProperty]
    public string Name { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }
    public string DepartmentName { get; set; }
    public Staff Leader { get; set; }
}

如果客戶不想要員工的領導信息,序列化:

void Main()
{
    Staff tom = new Staff { Name = "Tome", Age = 42, Gender = "Male", DepartmentName = "Personnel Department" };
    Staff jack = new Staff { Name = "Jack", Age = 30, Gender = "Male", DepartmentName = "Personnel Department", Leader = tom };
    string json = JsonConvert.SerializeObject(jack);
    Console.WriteLine(json);
    //{"Name":"Jack","Age":30,"Gender":"Male","DepartmentName":"Personnel Department"}
}

public class Staff
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }
    public string DepartmentName { get; set; }
    [JsonIgnore]
    public Staff Leader { get; set; }
}

五、支持非公共成員

Json.Net序列化對象時,默認情況下僅僅序列化公有成員,如果想要非公有成員也被序列化,就要在該成員上加特性"JsonProperty"。

六、日期處理

JsonConverters會在序列化和反序列化時被用到。JsonConverters允許手動對Json的控制。當Json的結(jié)構(gòu)很復雜和你想改變一個類型怎么樣被序列化時,這是非常有用的。

當一個JsonConverters被添加到JsonSerializer時,它會檢查每一個要被序列化和反序列化的值,并返回CanConvert,如果為True,則JsonConverter讀和寫這個值;

需要注意的是,雖然JsonConverter能夠使你可以完全的控制Json的值,但是很多的Json.Net序列化的特性被限制,像是類型名稱和引用處理。

所有的JsonConvert都在命名空間 "Newtonsoft.Json.Converters"下

1、使用IsoDateTimeConverter 和 JavaScriptDateTimeConverter標準格式

這是Json.Net中自帶的兩個處理日期的類:

  • IsoDateTimeConverter :默認的ISO"標準日期格式,它的格式是"yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"。
  • JavaScriptTimeConverter:它的格式是 "new Date(ticks)",其實返回的是一個JavaScript的Date對象.

有兩種方式來應用JsonConverter,改變Json序列化和反序列化的行為.

1、如果你要序列化的日期格式是統(tǒng)一的,可以考慮如下方式

假設我們?yōu)閱T工添加兩個日期類型的成員,出生日期和入職日期,我們的客戶要求日期類型的成員返回javascript的日期對象

void Main()
{
    Staff jack = new Staff
    {
        Name = "Jack",
        Age = 30,
        Gender = "Male",
        DepartmentName = "Personnel Department",
        BirthDate = new DateTime(1982, 2, 12),
        EmploymentDate = new DateTime(2010, 12, 12)
    };
    string json = JsonConvert.SerializeObject(jack, new JavaScriptDateTimeConverter());
    Console.WriteLine(json);
    //{"Name":"Jack","Age":30,"Gender":"Male","DepartmentName":"Personnel Department","Leader":null,"BirthDate":new Date(382291200000),"EmploymentDate":new Date(1292083200000)}
}

public class Staff
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }
    public string DepartmentName { get; set; }
    public Staff Leader { get; set; }
    public DateTime BirthDate { get; set; }
    public DateTime EmploymentDate { get; set; }
}

2、如果想要不同的日期類型成員序列化后,以不同的形式顯示.

現(xiàn)在我們的客戶要求出生日期以"ISO"標準日期格式返回,入職日期以Javascript的Date對象格式返回,修改我們的員工類,,通過特性"JsonConverter"來實現(xiàn)差異化。

void Main()
{
    Staff jack = new Staff
    {
        Name = "Jack",
        Age = 30,
        Gender = "Male",
        DepartmentName = "Personnel Department",
        BirthDate = new DateTime(1982, 2, 12),
        EmploymentDate = new DateTime(2010, 12, 12)
    };
    string json = JsonConvert.SerializeObject(jack);
    Console.WriteLine(json);
    //{"Name":"Jack","Age":30,"Gender":"Male","DepartmentName":"Personnel Department","Leader":null,"BirthDate":"1982-02-12T00:00:00","EmploymentDate":new Date(1292083200000)}
}

public class Staff
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }
    public string DepartmentName { get; set; }
    public Staff Leader { get; set; }
    [JsonConverter(typeof(IsoDateTimeConverter))]
    public DateTime BirthDate { get; set; }
    [JsonConverter(typeof(JavaScriptDateTimeConverter))]
    public DateTime EmploymentDate { get; set; }
}

2、自定義日期格式

要求返回的格式是"2012年4月20日"這種格式,使用“IsoDatetimeConverter"內(nèi)部的日期格式DefaultDateTimeFormat。

void Main()
{
    Staff jack = new Staff
    {
        Name = "Jack",
        Age = 30,
        Gender = "Male",
        DepartmentName = "Personnel Department",
        BirthDate = new DateTime(1982, 2, 12),
        EmploymentDate = new DateTime(2010, 12, 12)
    };
    IsoDateTimeConverter dtConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy'年'MM'月'dd'日'" };
    string json = JsonConvert.SerializeObject(jack, dtConverter);
    Console.WriteLine(json);
    //{"Name":"Jack","Age":30,"Gender":"Male","DepartmentName":"Personnel Department","Leader":null,"BirthDate":"1982年02月12日","EmploymentDate":"2010年12月12日"}
}

public class Staff
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Gender { get; set; }
    public string DepartmentName { get; set; }
    public Staff Leader { get; set; }
    public DateTime BirthDate { get; set; }
    [JsonConverter(typeof(JavaScriptDateTimeConverter))]
    public DateTime EmploymentDate { get; set; }
}

七、自定義序列化的字段名稱

默認情況下,Json.Net序列化后結(jié)果中的字段名稱和類中屬性的名稱一致.如果想自定義序列化后的字段名稱,可以使用JsonProperty.例如:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

默認序列化的結(jié)果為: {"Id":1,"Name":"楊過"},如果不想用默認的字段名稱,可以使用如下方式:

public class Person
{
    [JsonProperty(PropertyName = "PersonId")]
    public int Id { get; set; }

    [JsonProperty(PropertyName = "PersonName")]
    public string Name { get; set; }
}

這樣序列化的結(jié)果為:{"PersonId":1,"PersonName":"楊過"}

八、枚舉值的自定義格式化問題

默認情況下對于實體里面的枚舉類型系統(tǒng)是格式化成改枚舉對應的整型數(shù)值,那如果需要格式化成枚舉對應的字符怎么處理呢?Newtonsoft.Json也幫我們想到了這點,下面看實例

void Main()
{
    string json = JsonConvert.SerializeObject(new TestEnmu());
    Console.WriteLine(json);
    //{"Type":0}
}

public enum NotifyType
{
    /// 
    /// Emil發(fā)送
    /// 
    Mail = 0,

    /// 
    /// 短信發(fā)送
    /// 
    SMS = 1
}

public class TestEnmu
{
    /// 
    /// 消息發(fā)送類型
    /// 
    public NotifyType Type { get; set; }
}

現(xiàn)在改造一下,輸出"Type":"Mail"

public class TestEnmu
{
    /// 
    /// 消息發(fā)送類型
    /// 
    [JsonConverter(typeof(StringEnumConverter))]
    public NotifyType Type { get; set; }
}

其它的都不變,在Type屬性上加上了JsonConverter(typeof(StringEnumConverter))表示將枚舉值轉(zhuǎn)換成對應的字符串,而StringEnumConverter是Newtonsoft.Json內(nèi)置的轉(zhuǎn)換類型,最終輸出結(jié)果:{"Type":"Mail"}

九、Dynamic類型的序列化

在.Net4.0中,Dynamic基本上有兩種用法.

  • 第一種是作為屬性來用,在這種情況下序列化時會根據(jù)實際的類型來序列化。
  • 第二種用法是繼承了IDynamicMetaObjectProvider 接口或者DynamicObject基類。例如.Net中內(nèi)置的類ExpandoObject ,這三者之間的關系是:ExpandoObject,DynamicObject都繼承了IDynamicMetaObjectProvider. 
    這種情況下,只有DynamicMetaObject.GetDynamicMemberNames的返回的成員的屬性會被序列化.

首先新建一個類,繼承基類 DynamicObject,在主程序中,做如下操作:

void Main()
{
    dynamic md = new MyDynamic();//必須是用dynamic來聲明變量,不能用MyDynamic,否則它就不是動態(tài)類型了。
    md.Name = "Jack";
    Action<string> output = new Action<string>((value) => { Console.WriteLine(value); });
    md.Output = output;
    Console.WriteLine(JsonConvert.SerializeObject(md));
    md.Output(md.Name);

    //{ "Name":"Jack","Output":{ "Delegate":{ },"target0":{ },"method0":{ "Name":"
b__0_0","AssemblyName":"query_dmdxhj, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null","ClassName":"UserQuery+<>c","Signature":"Void 
b__0_0(System.String)","Signature2":"System.Void 
b__0_0(System.String)","MemberType":8,"GenericArguments":null} } }
    //Jack
}

public class MyDynamic : DynamicObject
{
    //用來存儲動態(tài)添加的變量和值
    private Dictionary<string, object> members = new Dictionary<string, object>();

    /// 

    /// 獲取所有的動態(tài)成員名稱
    /// 
    /// 動態(tài)成員名稱
    public override IEnumerable<string> GetDynamicMemberNames()
    {
        return members.Keys;
    }

    /// 

    /// 設置動態(tài)成員名稱,也就是在發(fā)生賦值語句時出發(fā)該方法
    /// 例如:dynamic dy = new MyDynamic();
    /// dy.Name = "Jack";
    /// 
    /// 用于動態(tài)設置操作
    /// 預設的值
    /// 
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        if (!members.ContainsKey(binder.Name))
        {
            members.Add(binder.Name, value);
        }
        else
            members[binder.Name] = value;
        return true;
    }

    /// 

    /// 根據(jù)名稱獲取動態(tài)成員的值
    ///  例如:dynamic dy = new MyDynamic();
    ///  var name = dy.Name;
    /// 
    /// 用戶動態(tài)獲取操作
    /// 將獲取的值賦給的對象
    /// 

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (members.ContainsKey(binder.Name))
        {
            result = members[binder.Name];
            return true;
        }
        else
            return base.TryGetMember(binder, out result);
    }

    /// 

    /// 如果成員的類型是委托,則調(diào)用它
    /// 
    /// 用戶動態(tài)委托操作
    /// 委托調(diào)用的參數(shù)
    /// 委托調(diào)用返回的結(jié)果
    /// 
    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        if (members.ContainsKey(binder.Name) && members[binder.Name] is Delegate)
        {
            result = (members[binder.Name] as Delegate).DynamicInvoke(args);
            return true;
        }
        else
        {
            return base.TryInvokeMember(binder, args, out result);
        }
    }
}

是的,委托類型也被序列化了,這并不是我們想要的,有沒有方法來將它排除呢?答案就在GetDynamicMemberNames方法,默認我們返回的是所有的Keys,只要我們加一定的限制條件即可.修改之后的代碼

public override IEnumerable<string> GetDynamicMemberNames()
{
    foreach (string key in members.Keys)
    {
        if (!(members[key] is Delegate))
            yield return key;
    }
}

此時的運行結(jié)果:

{"Name":"Jack"} 
Jack

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

最新評論