如何在 C# 中正确反序列化 JSON
How do I deserialize JSON correctly in C#
我正在尝试反序列化 Supreme New York JSON,但出现错误。
我使用 json2csharp.com
将 Json 转换为 类。
然后我把它们总结成一个叫做items
namespace SUPBOTTESTING
{
public class items
{
public string name { get; set; }
public int id { get; set; }
public string image_url { get; set; }
public string image_url_hi { get; set; }
public int price { get; set; }
public int sale_price { get; set; }
public bool new_item { get; set; }
public int position { get; set; }
public string category_name { get; set; }
public int price_euro { get; set; }
public int sale_price_euro { get; set; }
}
}
using System;
using System.Net;
using System.Web.Script.Serialization;
namespace SUPBOTTESTING
{
class Program
{
public static void Main()
{
{
string shop_json = new WebClient().DownloadString("https://www.supremenewyork.com/mobile_stock.json");
JavaScriptSerializer shop_object = new JavaScriptSerializer();
items[] shirt_stock = shop_object.Deserialize<items[]>(shop_json);
Console.WriteLine(shirt_stock[1]);
}
}
}
}
我收到错误:
Default constructor not found for type SUPBOTTESTING.items[]
你的问题是你正在使用 class 加载 JSON 数据,你应该在其中使用结构,或者你也可以创建一个不带参数并设置所有变量的构造函数默认值,这是很多工作所以只需将 class
替换为 struct
:
public struct Items
{
public string Name { get; set; }
public int Id { get; set; }
public string Image_Url { get; set; }
public string Image_Url_Hi { get; set; }
public int Price { get; set; }
public int Sale_Price { get; set; }
public bool New_item { get; set; }
public int Position { get; set; }
public string Category_Name { get; set; }
public int Price_Euro { get; set; }
public int Sale_Price_Euro { get; set; }
}
另外请遵守 C# 命名约定,您应该能够做到这一点,因为大多数 JSON 解析器默认不区分大小写。
一些更多的信息:如果你不定义一个 class 实际上没有一个合适的默认构造函数,因为结构总是有一个默认构造函数,所以当 JSON 解析器想要初始化时你的 class 它不能,因为没有定义默认构造函数。
好吧,您不需要指定默认构造函数。问题是,我认为您没有正确检查 json 数据。因为你的items
class不在json的第一层。您需要创建几个 classes 才能在反序列化时更加准确。
首先你需要知道这个 json
文件有很多不好的味道和不好的做法。
请注意,您需要先安装 Newtonsoft.Json
,然后再继续。将 json 反序列化为 C# classes.
是一种更方便的方法
然而,我写了一个正确的反序列化方法:
public class BaseItem
{
public string Name { get; set; }
public int Id { get; set; }
public string Image_url { get; set; }
public string Image_url_hi { get; set; }
public int Price { get; set; }
public int Sale_price { get; set; }
public bool New_item { get; set; }
public int Position { get; set; }
public string Category_name { get; set; }
public int Price_euro { get; set; }
public int Sale_price_euro { get; set; }
}
public class Shirt : BaseItem { }
public class Bag : BaseItem { }
public class Accessory : BaseItem { }
public class Pant : BaseItem { }
public class Jacket : BaseItem { }
public class Skate : BaseItem { }
public class Hat : BaseItem { }
public class Sweatshirt : BaseItem { }
public class TopsSweater : BaseItem { }
public class New : BaseItem { }
public class RootObject
{
public List<object> Unique_image_url_prefixes { get; set; }
public ProductsAndCategories Products_and_categories { get; set; }
public string Release_date { get; set; }
public string Release_week { get; set; }
}
public class ProductsAndCategories
{
public List<Shirt> Shirts { get; set; }
public List<Bag> Bags { get; set; }
public List<Accessory> Accessories { get; set; }
public List<Pant> Pants { get; set; }
public List<Jacket> Jackets { get; set; }
public List<Skate> Skate { get; set; }
public List<Hat> Hats { get; set; }
public List<Sweatshirt> Sweatshirts { get; set; }
[JsonProperty("Tops/Sweaters")]
public List<TopsSweater> TopsSweaters { get; set; }
public List<New> New { get; set; }
}
首先,您的所有物品都具有相同的属性,但它们都标记为不同的属性。因此,我创建了一个 BaseItem
class 和其他从中继承的空 classes。
您还需要其他 2 个 classes - 即 RootObject
和 ProductsAndCategories
- 来提供有关它们的数据。注意 TopsSweaters
属性 上有一个 JsonProperty("blabla")
。因为,在 json 文件中它是 Tops/Sweaters
,并且您不能在 C# 属性 上使用该名称。这就是使用那种不同的 属性 名称的属性。
然后您可以像这样填充您的对象:
static void Main(string[] args)
{
var jsonData = "https://www.supremenewyork.com/mobile_stock.json";
string shopJson = new WebClient().DownloadString(jsonData);
RootObject shirtStock = JsonConvert.DeserializeObject<RootObject>(shopJson); //All json data is in this variable
Console.WriteLine(shirtStock.Products_and_categories.Shirts[1]);
}
好的,这是解决方案。您的想法是正确的,但您需要了解 Json 数据的结构。
你是deserializing
它进入一个Object
的数组,而你的Json返回的数据本身不是数组或列表。它包含作为数组的子节点,因此您需要相应地构建 Object
以成功分解数据。
这里我使用 Newtonsoft
将 Json 数据反序列化为对象。
我已经测试了代码,它 returns 是 Shirts
的列表
static void Main(string[] args)
{
var shop_json = new WebClient().DownloadString("https://www.supremenewyork.com/mobile_stock.json");
var shirt_stock = JsonConvert.DeserializeObject<StockObject>(shop_json);
// Picking shirts to demonstrate how to display values for all shirts
var shirts = shirt_stock.products_and_categories.Shirts;
foreach (var shirt in shirts)
{
var shirtBuilder = new StringBuilder();
shirtBuilder.AppendLine($"Name: {shirt.name}");
shirtBuilder.AppendLine($"ID: {shirt.id.ToString()}");
shirtBuilder.AppendLine($"New Item: {shirt.new_item.ToString()}");
shirtBuilder.AppendLine($"Category Name: {shirt.category_name}");
Console.WriteLine(shirtBuilder);
}
}
public class StockObject
{
public ProductsCats Products_and_categories { get; set; }
}
public class ProductsCats
{
public Details[] Shirts { get; set; }
public Details[] Bags { get; set; }
public Details[] Accessories { get; set; }
public Details[] Pants { get; set; }
public Details[] Jackets { get; set; }
public Details[] Skates { get; set; }
public Details[] Hats { get; set;}
public Details[] Sweatshirts { get; set;}
[JsonProperty("Tops/Sweaters")]
public Details[] TopsSweaters { get;set;}
public Details[] New { get; set; }
}
public class Details
{
public string name { get; set; }
public int id { get; set; }
public string image_url { get; set; }
public string image_url_hi { get; set; }
public int price { get; set; }
public int sale_price { get; set; }
public bool new_item { get; set; }
public int position { get; set; }
public string category_name { get; set; }
public int price_euro { get; set; }
public int sale_price_euro { get; set; }
}
你看到我在这里做了什么吗?
所以你的 Json 数据包含一个父节点 products_and_categories
并且它的子节点包含一个 Shirts
的数组,这就是你想要的?
StockObject
class 包含对象 ProductsCats
类型 Products_and_categories
的 Parent
属性。
ProductsCats
对象包含 Details
类型的 属性 Shirts
,它是一个数组,将在 deserialising
过程中使用。
希望这有帮助吗?
static void Main(string[] args)
{
string shop_json = new WebClient().DownloadString("https://www.supremenewyork.com/mobile_stock.json");
JavaScriptSerializer shop_object = new JavaScriptSerializer();
var shirt_stock = shop_object.Deserialize<NewYarkItems>(shop_json);
var v = shirt_stock;
}
public class NewYarkItems
{
public dynamic unique_image_url_prefixes { get; set; }
public products_and_categories products_And_Categories { get; set; }
public string release_date { get; set; }
public string release_week { get; set; }
}
public class products_and_categories
{
public List<items> Jackets { get; set; }
}
public class items
{
public string name { get; set; }
public int id { get; set; }
public string image_url { get; set; }
public string image_url_hi { get; set; }
public int price { get; set; }
public int sale_price { get; set; }
public bool new_item { get; set; }
public int position { get; set; }
public string category_name { get; set; }
public int price_euro { get; set; }
public int sale_price_euro { get; set; }
}
我正在尝试反序列化 Supreme New York JSON,但出现错误。
我使用 json2csharp.com
将 Json 转换为 类。
然后我把它们总结成一个叫做items
namespace SUPBOTTESTING
{
public class items
{
public string name { get; set; }
public int id { get; set; }
public string image_url { get; set; }
public string image_url_hi { get; set; }
public int price { get; set; }
public int sale_price { get; set; }
public bool new_item { get; set; }
public int position { get; set; }
public string category_name { get; set; }
public int price_euro { get; set; }
public int sale_price_euro { get; set; }
}
}
using System;
using System.Net;
using System.Web.Script.Serialization;
namespace SUPBOTTESTING
{
class Program
{
public static void Main()
{
{
string shop_json = new WebClient().DownloadString("https://www.supremenewyork.com/mobile_stock.json");
JavaScriptSerializer shop_object = new JavaScriptSerializer();
items[] shirt_stock = shop_object.Deserialize<items[]>(shop_json);
Console.WriteLine(shirt_stock[1]);
}
}
}
}
我收到错误:
Default constructor not found for type SUPBOTTESTING.items[]
你的问题是你正在使用 class 加载 JSON 数据,你应该在其中使用结构,或者你也可以创建一个不带参数并设置所有变量的构造函数默认值,这是很多工作所以只需将 class
替换为 struct
:
public struct Items
{
public string Name { get; set; }
public int Id { get; set; }
public string Image_Url { get; set; }
public string Image_Url_Hi { get; set; }
public int Price { get; set; }
public int Sale_Price { get; set; }
public bool New_item { get; set; }
public int Position { get; set; }
public string Category_Name { get; set; }
public int Price_Euro { get; set; }
public int Sale_Price_Euro { get; set; }
}
另外请遵守 C# 命名约定,您应该能够做到这一点,因为大多数 JSON 解析器默认不区分大小写。
一些更多的信息:如果你不定义一个 class 实际上没有一个合适的默认构造函数,因为结构总是有一个默认构造函数,所以当 JSON 解析器想要初始化时你的 class 它不能,因为没有定义默认构造函数。
好吧,您不需要指定默认构造函数。问题是,我认为您没有正确检查 json 数据。因为你的items
class不在json的第一层。您需要创建几个 classes 才能在反序列化时更加准确。
首先你需要知道这个 json
文件有很多不好的味道和不好的做法。
请注意,您需要先安装 Newtonsoft.Json
,然后再继续。将 json 反序列化为 C# classes.
然而,我写了一个正确的反序列化方法:
public class BaseItem
{
public string Name { get; set; }
public int Id { get; set; }
public string Image_url { get; set; }
public string Image_url_hi { get; set; }
public int Price { get; set; }
public int Sale_price { get; set; }
public bool New_item { get; set; }
public int Position { get; set; }
public string Category_name { get; set; }
public int Price_euro { get; set; }
public int Sale_price_euro { get; set; }
}
public class Shirt : BaseItem { }
public class Bag : BaseItem { }
public class Accessory : BaseItem { }
public class Pant : BaseItem { }
public class Jacket : BaseItem { }
public class Skate : BaseItem { }
public class Hat : BaseItem { }
public class Sweatshirt : BaseItem { }
public class TopsSweater : BaseItem { }
public class New : BaseItem { }
public class RootObject
{
public List<object> Unique_image_url_prefixes { get; set; }
public ProductsAndCategories Products_and_categories { get; set; }
public string Release_date { get; set; }
public string Release_week { get; set; }
}
public class ProductsAndCategories
{
public List<Shirt> Shirts { get; set; }
public List<Bag> Bags { get; set; }
public List<Accessory> Accessories { get; set; }
public List<Pant> Pants { get; set; }
public List<Jacket> Jackets { get; set; }
public List<Skate> Skate { get; set; }
public List<Hat> Hats { get; set; }
public List<Sweatshirt> Sweatshirts { get; set; }
[JsonProperty("Tops/Sweaters")]
public List<TopsSweater> TopsSweaters { get; set; }
public List<New> New { get; set; }
}
首先,您的所有物品都具有相同的属性,但它们都标记为不同的属性。因此,我创建了一个 BaseItem
class 和其他从中继承的空 classes。
您还需要其他 2 个 classes - 即 RootObject
和 ProductsAndCategories
- 来提供有关它们的数据。注意 TopsSweaters
属性 上有一个 JsonProperty("blabla")
。因为,在 json 文件中它是 Tops/Sweaters
,并且您不能在 C# 属性 上使用该名称。这就是使用那种不同的 属性 名称的属性。
然后您可以像这样填充您的对象:
static void Main(string[] args)
{
var jsonData = "https://www.supremenewyork.com/mobile_stock.json";
string shopJson = new WebClient().DownloadString(jsonData);
RootObject shirtStock = JsonConvert.DeserializeObject<RootObject>(shopJson); //All json data is in this variable
Console.WriteLine(shirtStock.Products_and_categories.Shirts[1]);
}
好的,这是解决方案。您的想法是正确的,但您需要了解 Json 数据的结构。
你是deserializing
它进入一个Object
的数组,而你的Json返回的数据本身不是数组或列表。它包含作为数组的子节点,因此您需要相应地构建 Object
以成功分解数据。
这里我使用 Newtonsoft
将 Json 数据反序列化为对象。
我已经测试了代码,它 returns 是 Shirts
static void Main(string[] args)
{
var shop_json = new WebClient().DownloadString("https://www.supremenewyork.com/mobile_stock.json");
var shirt_stock = JsonConvert.DeserializeObject<StockObject>(shop_json);
// Picking shirts to demonstrate how to display values for all shirts
var shirts = shirt_stock.products_and_categories.Shirts;
foreach (var shirt in shirts)
{
var shirtBuilder = new StringBuilder();
shirtBuilder.AppendLine($"Name: {shirt.name}");
shirtBuilder.AppendLine($"ID: {shirt.id.ToString()}");
shirtBuilder.AppendLine($"New Item: {shirt.new_item.ToString()}");
shirtBuilder.AppendLine($"Category Name: {shirt.category_name}");
Console.WriteLine(shirtBuilder);
}
}
public class StockObject
{
public ProductsCats Products_and_categories { get; set; }
}
public class ProductsCats
{
public Details[] Shirts { get; set; }
public Details[] Bags { get; set; }
public Details[] Accessories { get; set; }
public Details[] Pants { get; set; }
public Details[] Jackets { get; set; }
public Details[] Skates { get; set; }
public Details[] Hats { get; set;}
public Details[] Sweatshirts { get; set;}
[JsonProperty("Tops/Sweaters")]
public Details[] TopsSweaters { get;set;}
public Details[] New { get; set; }
}
public class Details
{
public string name { get; set; }
public int id { get; set; }
public string image_url { get; set; }
public string image_url_hi { get; set; }
public int price { get; set; }
public int sale_price { get; set; }
public bool new_item { get; set; }
public int position { get; set; }
public string category_name { get; set; }
public int price_euro { get; set; }
public int sale_price_euro { get; set; }
}
你看到我在这里做了什么吗?
所以你的 Json 数据包含一个父节点 products_and_categories
并且它的子节点包含一个 Shirts
的数组,这就是你想要的?
StockObject
class 包含对象 ProductsCats
类型 Products_and_categories
的 Parent
属性。
ProductsCats
对象包含 Details
类型的 属性 Shirts
,它是一个数组,将在 deserialising
过程中使用。
希望这有帮助吗?
static void Main(string[] args)
{
string shop_json = new WebClient().DownloadString("https://www.supremenewyork.com/mobile_stock.json");
JavaScriptSerializer shop_object = new JavaScriptSerializer();
var shirt_stock = shop_object.Deserialize<NewYarkItems>(shop_json);
var v = shirt_stock;
}
public class NewYarkItems
{
public dynamic unique_image_url_prefixes { get; set; }
public products_and_categories products_And_Categories { get; set; }
public string release_date { get; set; }
public string release_week { get; set; }
}
public class products_and_categories
{
public List<items> Jackets { get; set; }
}
public class items
{
public string name { get; set; }
public int id { get; set; }
public string image_url { get; set; }
public string image_url_hi { get; set; }
public int price { get; set; }
public int sale_price { get; set; }
public bool new_item { get; set; }
public int position { get; set; }
public string category_name { get; set; }
public int price_euro { get; set; }
public int sale_price_euro { get; set; }
}