Json、Xml
JSON
将.net实例对象转换为json字符串。
需要依赖项 Nuget 包:Newtonsoft.Json
序列化与反序列化
将结果放在内存中
public class Product
{
public int ProductID { get; set; }
public string ProductName { get; set; }
public int SupplierID { get; set; }
public string ISBN { get; set; }
}
public class Inventory
{
public Product[] IventoryItems { get; set; }
}
填充示例对象
static Inventory GetInventory() =>
new Inventory
{
IventoryItems = new Product[]
{
new Product
{
ProductID = 100,
ProductName = "Product Thing",
SupplierID = 10
},
new Product
{
ProductID = 101,
ProductName = "How to Use Your New Product Thing",
ISBN = "1234567890"
}
}
};
序列化和反序列化
static void ConvertObject()
{
// 实例对象
Inventory inventory = GetInventory();
// 序列化
string json = JsonConvert.SerializeObject(inventory,Formatting.Indented);
Console.WriteLine(json);
// 反序列化
Inventory newInventory = JsonConvert.DeserializeObject<Inventory>(json);
foreach (var product in newInventory.IventoryItems)
{
Console.WriteLine(product);
}
}
将结果保存到本地
序列化:
static void SerializeJson()
{
using (var outputStream = File.CreateText(InventoryFileName))
{
JsonSerializer serializer = JsonSerializer.Create(
new JsonSerializerSettings { Formatting = Formatting.Indented});
serializer.Serialize(outputStream,GetInventory());
}
}
其中InventoryFileName为本地路径,用于保存序列化后的json字符串。
反序列化:
static void DeserializeJson()
{
using (var reader = File.OpenText(InventoryFileName))
{
JsonSerializer serializer = JsonSerializer.Create();
Inventory inventory = serializer.Deserialize(reader,typeof(Inventory)) as Inventory;
foreach (var item in inventory.IventoryItems)
{
Console.WriteLine(item.ProductName);
}
}
}
其中InventoryFileName为本地路径,读取json文件以用于反序列化。
使用代码创建Json对象(JObject)
static void CreateJson()
{
var book1 = new JObject();
book1["title"] = "Professional C# 7 and .NET Core 2.0";
book1["publisher"] = "Wrox Press";
var book2 = new JObject();
book2["title"] = "Professional C# 6 and .NET Core 1.0";
book2["publisher"] = "Wrox Press";
var books = new JArray();
books.Add(book1);
books.Add(book2);
var json = new JObject();
json["books"] = books;
Console.WriteLine(json);
}
输出的字符串表示形式如下:
{
"books": [
{
"title": "Professional C# 7 and .NET Core 2.0",
"publisher": "Wrox Press"
},
{
"title": "Professional C# 6 and .NET Core 1.0",
"publisher": "Wrox Press"
}
]
}
从.json文件中读取
static void ReaderSample()
{
StreamReader reader = File.OpenText(InventoryFileName);
using (JsonTextReader jsonReader = new JsonTextReader(reader) { CloseInput = true})
{
while (jsonReader.Read())
{
Console.Write($"token: {jsonReader.TokenType}, ");
if (!string.IsNullOrEmpty(jsonReader.Path))
{
Console.Write($"path: {jsonReader.Path}, ");
}
if (!string.IsNullOrEmpty(jsonReader.Value?.ToString()))
{
Console.Write($"value: {jsonReader.Value}");
}
Console.WriteLine();
}
}
}
XML
序列化与反序列化
声明一个字段,其内容为xml文档文件的本地路径。
//xml文档的本地路径,用于写入(序列化)和读取(反序列化)
private const string InventoryFileName = "products.xml";
准备示例对象模型:
类Product
[XmlRoot]
public class Product
{
//[XmlAttribute(AttributeName = "Discount")]
[XmlElement]
public int Discount { get; set; }
[XmlElement]
public int ProductID { get; set; }
[XmlElement]
public string ProductName { get; set; }
[XmlElement]
public int SupplierID { get; set; }
[XmlElement]
public int CategoryID { get; set; }
[XmlElement]
public string QuantityPerUnit { get; set; }
[XmlElement]
public decimal UnitPrice { get; set; }
[XmlElement]
public short UnitsInStock { get; set; }
[XmlElement]
public short UnitsOnOrder { get; set; }
[XmlElement]
public short ReorderLevel { get; set; }
[XmlElement]
public bool Discontinued { get; set; }
public override string ToString()
{
return $"{ProductID} {ProductName} {UnitPrice:C}";
}
}
Products
public class Products
{
public List<Product> ProductsValue { get; set; }
}
派生自Product的BookProduct
public class BookProduct:Product
{
//[XmlAttribute("Isbn")]
public string ISBN { get; set; }
}
Inventory类,包含Procuct类型数组
public class Inventory
{
//[XmlArrayItem("Product",typeof(Product))]
//[XmlArrayItem("Book",typeof(BookProduct))]
public Product[] InventoryItems { get; set; }
public override string ToString()
{
var outText = new StringBuilder();
foreach (var prod in InventoryItems)
{
outText.AppendLine(prod.ProductName);
}
return outText.ToString();
}
}
序列化
定义特性:
static XmlAttributeOverrides GetInventoryXmlAttributes()
{
var inventoryAttributes = new XmlAttributes();
inventoryAttributes.XmlArrayItems.Add(new XmlArrayItemAttribute("Book", typeof(BookProduct)));
inventoryAttributes.XmlArrayItems.Add(new XmlArrayItemAttribute("Product", typeof(Product)));
var bookIsbnAttributes = new XmlAttributes();
bookIsbnAttributes.XmlAttribute = new XmlAttributeAttribute("Isbn");
var productDiscountAttributes = new XmlAttributes();
productDiscountAttributes.XmlAttribute = new XmlAttributeAttribute("Discount");
var overrides = new XmlAttributeOverrides();
overrides.Add(typeof(Inventory), "InventoryItems", inventoryAttributes);
overrides.Add(typeof(BookProduct), "ISBN", bookIsbnAttributes);
overrides.Add(typeof(Product), "Discount", productDiscountAttributes);
return overrides;
}
static void SerializerInventory()
{
var product = new Product
{
ProductID = 100,
ProductName = "Product Thing",
SupplierID = 10
};
var book = new BookProduct
{
ProductID = 101,
ProductName = "How to Use Your New Product Thing",
SupplierID = 10,
ISBN = "1234567890"
};
Product[] items = { product, book };
var inventory = new Inventory
{
InventoryItems = items
};
using (var outputStream = File.Create(InventoryFileName))
{
var serializer = new XmlSerializer(typeof(Inventory),
GetInventoryXmlAttributes());
serializer.Serialize(outputStream, inventory);
}
}
打开 products.xml 文件,查看写入的xml内容:
<?xml version="1.0"?>
<Inventory xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<InventoryItems>
<Product Discount="0">
<ProductID>100</ProductID>
<ProductName>Product Thing</ProductName>
<SupplierID>10</SupplierID>
<CategoryID>0</CategoryID>
<UnitPrice>0</UnitPrice>
<UnitsInStock>0</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>0</ReorderLevel>
<Discontinued>false</Discontinued>
</Product>
<Book Discount="0" Isbn="1234567890">
<ProductID>101</ProductID>
<ProductName>How to Use Your New Product Thing</ProductName>
<SupplierID>10</SupplierID>
<CategoryID>0</CategoryID>
<UnitPrice>0</UnitPrice>
<UnitsInStock>0</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>0</ReorderLevel>
<Discontinued>false</Discontinued>
</Book>
</InventoryItems>
</Inventory>
序列化产品列表(Products)
static void SerializeProducts()
{
var products = new Products
{
ProductsValue = new List<Product>
{
new Product
{
ProductID = 0,
ProductName = "one product",
UnitPrice = 100
},
new Product
{
ProductID = 1,
ProductName = "two product",
UnitPrice = 200
},
new Product
{
ProductID = 2,
ProductName = "three product",
UnitPrice = 300
}
}
};
using (var outputStream = File.OpenWrite(InventoryFileName))
{
var serializer = new XmlSerializer(typeof(Products));
serializer.Serialize(outputStream, products);
}
}
写入到文件的内容:
<?xml version="1.0"?>
<Products xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ProductsValue>
<Product>
<Discount>0</Discount>
<ProductID>0</ProductID>
<ProductName>one product</ProductName>
<SupplierID>0</SupplierID>
<CategoryID>0</CategoryID>
<UnitPrice>100</UnitPrice>
<UnitsInStock>0</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>0</ReorderLevel>
<Discontinued>false</Discontinued>
</Product>
<Product>
<Discount>0</Discount>
<ProductID>1</ProductID>
<ProductName>two product</ProductName>
<SupplierID>0</SupplierID>
<CategoryID>0</CategoryID>
<UnitPrice>200</UnitPrice>
<UnitsInStock>0</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>0</ReorderLevel>
<Discontinued>false</Discontinued>
</Product>
<Product>
<Discount>0</Discount>
<ProductID>2</ProductID>
<ProductName>three product</ProductName>
<SupplierID>0</SupplierID>
<CategoryID>0</CategoryID>
<UnitPrice>300</UnitPrice>
<UnitsInStock>0</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>0</ReorderLevel>
<Discontinued>false</Discontinued>
</Product>
</ProductsValue>
</Products>
反序列化
反序列化 Inventory 对象实例(包含Product类型数组):
static void DeserializeInventory()
{
using (var inputStream = File.OpenRead(InventoryFileName))
{
var serializer = new XmlSerializer(typeof(Inventory));
Inventory newInventory = serializer.Deserialize(inputStream) as Inventory;
//foreach (var prod in newInventory.InventoryItems)
//{
// Console.WriteLine(prod.ProductName);
//}
Console.WriteLine(newInventory);
}
}
得到一个 Inventory 实例,Inventory 重写了 ToString() 方法,输出如下:
Product Thing
How to Use Your New Product Thin
注意,需要取消Inventory中的注释,如下:
public class Inventory
{
//为了使反序列化得到正确的结果,需要取消下面的注释
//[XmlArrayItem("Product", typeof(Product))]
//[XmlArrayItem("Book", typeof(BookProduct))]
public Product[] InventoryItems { get; set; }
public override string ToString()
{
var outText = new StringBuilder();
foreach (var prod in InventoryItems)
{
outText.AppendLine(prod.ProductName);
}
return outText.ToString();
}
}
创建XML文档
// 写入xml路径
private const string ProductsFileName = "/Users/wangxianguo/Desktop/products.xml";
// 读取xml路径
private const string HamleFileName = "/Users/wangxianguo/Desktop/hamlet.xml";
Create Xml
static void CreateXml()
{
XNamespace ns = "http://www.cninnovation.com/samples/2018";
XNamespace ns2 = "http://www.cninnovation.com/samples/2018/address";
var doc = new XDocument();
XComment comment = new XComment("Sample XML for Professional C#.");
doc.Add(comment);
var company = new XElement(ns+"Company",
new XElement(ns2+"CompanyName","Microsoft Corporation"),
new XAttribute("TaxId","91-1144442"),
new XElement(ns2+"CompanyAddress",
new XElement("Address","One Microsoft Way"),
new XElement("City","Redmond"),
new XElement("Zip","WA 98052-6399"),
new XElement("State","WA"),
new XElement("Country","USA")));
using (var outputStream = File.OpenWrite(ProductsFileName))
{
//company.Save(outputStream);
doc.Add(company);
Console.WriteLine(doc);
doc.Save(outputStream);
}
}
Query Xml with Linq
static void QueryHamlet()
{
XDocument doc = XDocument.Load(HamleFileName);
//Console.WriteLine(doc);
IEnumerable<string> persons =
(from people in doc.Descendants("PERSONA")
select people.Value).ToList();
Console.WriteLine($"{persons.Count()} Players Found");
Console.WriteLine();
foreach (var item in persons)
{
Console.WriteLine(item);
}
}
static async Task QueryFeed()
{
try
{
var httpClient = new HttpClient();
using (var stream = await httpClient.GetStreamAsync("http://csharp.christiannagel.com/feed/"))
{
XElement elements = XElement.Load(stream);
Console.WriteLine(elements);
XNamespace NS = "http://www.w3.org/2005/Atom";
XDocument doc = XDocument.Load(stream);
Console.WriteLine($"Title: {doc.Root.Element(NS + "title").Value}");
Console.WriteLine($"Subtitle: {doc.Root.Element(NS + "{subtitle}").Value}");
string url = doc.Root.Elements(NS + "link")
.Where(e => e.Attribute("rel").Value == "alternate")
.FirstOrDefault()
?.Attribute("href")
?.Value;
Console.WriteLine($"Link: {url}");
Console.WriteLine();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine($"inner exception: {ex.InnerException}");
}
}
Transforming to Objects
static void TransformingToObjects()
{
XDocument doc = XDocument.Load(HamleFileName);
var groups = doc.Descendants("PGROUP")
.Select((g,i)=>
new
{
Number = i+1,
Description = g.Element("GRPDESCR").Value,
Characters = g.Elements("PERSONA")
.Select(p=>p.Value)
});
foreach (var group in groups)
{
Console.WriteLine(group.Number);
Console.WriteLine(group.Description);
foreach (var name in group.Characters)
{
Console.WriteLine(name);
}
Console.WriteLine();
}
}
Transforming to Xml
static void TransformingToXml()
{
XDocument doc = XDocument.Load(HamleFileName);
var hamlet =
new XElement("hamlet",
doc.Descendants("PGROUP")
.Select((g,i)=>
new XElement("group",
new XAttribute("number", i+1),
new XAttribute("description", g.Element("GRPDESCR").Value),
new XElement("characters",
g.Elements("PERSONA")
.Select(p=>new XElement("name",p.Value))))
));
Console.WriteLine(hamlet);
}