简体   繁体   English

如何在C#中正确反序列化JSON

[英]How do I deserialize JSON correctly in C#

I am trying to deserialize the Supreme New York JSON but I am getting an error. 我正在尝试反序列化Supreme纽约JSON,但出现错误。

I used json2csharp.com to convert the Json into classes. 我使用json2csharp.com将Json转换为类。

Then I summarised them all into one called items 然后我将它们全部归纳为一个称为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]);

            }
        }
    }
}

I am getting the error: 我收到错误消息:

Default constructor not found for type SUPBOTTESTING.items[] 找不到类型SUPBOTTESTING.items []的默认构造函数

Well you do not need to specify a default constructor. 好了,您无需指定默认构造函数。 What is wrong is, i think you didn't check the json data properly. 问题是,我认为您没有正确检查json数据。 Because your items class is not in the first level of json. 因为您的items类不在json的第一级中。 You need to create a couple of classes to be more accurate on deserializing. 您需要创建几个类才能在反序列化方面更加准确。

First of all you need to know that this json file has a lot of bad-smells and bad-practices on it. 首先,您需要知道此json文件上有很多不良气味和不良做法。

Note that you need to install Newtonsoft.Json before going further. 请注意,您需要先安装Newtonsoft.Json然后再进行操作。 It is much more convenient way to deserialize a json into C# classes. 将json反序列化为C#类的方法更加方便。

Yet, i wrote a proper way of deserializing it: 但是,我写了一种反序列化的正确方法:

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; }
}

First of all, all of your items are have the same properties on them, yet, they all marked as different properties. 首先,所有项目的属性都相同,但是,它们都标记为不同的属性。 So that, i created a BaseItem class and other empty classes which are inherited from that. 因此,我创建了一个BaseItem类以及从中继承的其他空类。

Also you need other 2 classes -which are RootObject and ProductsAndCategories - to provide data on them. 另外,您还需要其他2个类RootObjectProductsAndCategories来提供有关它们的数据。 Note that there is a JsonProperty("blabla") on the TopsSweaters property. 请注意, TopsSweaters属性上有一个JsonProperty("blabla") Because, in json file it is Tops/Sweaters , and you can not use that name on a C# property. 因为,在json文件中,它是Tops/Sweaters ,并且您不能在C#属性上使用该名称。 That is the attribute for using that kind of different property names. 这是使用那种不同属性名称的属性。

Then you can populate your object like this: 然后,您可以像这样填充对象:

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]);
    }

Ok here is the solution. 好的,这是解决方案。 You have the correct idea but you need to understand the structure of your Json data. 您有正确的想法,但需要了解Json数据的结构。

You are deserializing it into an array of Object whereas your Json data returned itself is not an Array or a List. 您将其deserializing化为Object数组,而返回的Json数据本身不是Array或List。 It contains child nodes that are an array so you need to structure your Object accordingly to get a successful breakdown of data. 它包含作为数组的子节点,因此您需要相应地构造Object以获得成功的数据分解。

Here I have used Newtonsoft to deserialise the Json data into an Object. 在这里,我已使用Newtonsoft将Json数据反序列化为对象。

I have tested the code and it returns a list of Shirts 我已经测试了代码,它返回了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; }
}

You see what I have done here? 你看我在这里做什么?

So your Json data contains a parent node products_and_categories and its child node contains an array of Shirts which is what you are after? 因此,您的Json数据包含一个父节点products_and_categories ,其子节点包含一个Shirts数组,这是您想要的吗?

StockObject class contains the Parent property called Products_and_categories of type object ProductsCats . StockObject类包含类型为Products_and_categoriesParent属性,称为ProductsCats

ProductsCats Object contains the property Shirts of type Details which is an array and will be used during the deserialising process. ProductsCats对象包含属性Shirts型的Details这是一个数组,将在可以使用deserialising过程。

Hope this helps? 希望这可以帮助?

Your problem is that youre using a class to load the JSON data in, where you should use a struct, alternatively you can also create a constructor that takes no arguments and sets all variables to default values, which is a lot of work so just replace class with struct : 您的问题是您使用类来加载JSON数据,您应该在其中使用结构,或者您也可以创建不带参数的构造函数,并将所有变量设置为默认值,这是很多工作,因此只需替换带有struct class

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; }
}

Also please stick to C# naming conventions, you should be able to do this since most JSON parsers are case insensitive by default. 另外,请遵守C#命名约定,因为大多数JSON解析器默认情况下都不区分大小写,因此您应该能够执行此操作。

Some more info: A class doesnt really has a proper default constructor if you dont define one, where as a struct always has a default constructor, so when the JSON parser wants to init your class it cant because a default constructor isnt definded. 更多信息:如果您没有定义一个类,则该类实际上并没有适当的默认构造函数,因为结构始终具有一个默认构造函数,因此,当JSON解析器要初始化您的类时,它将无法启动,因为未定义默认构造函数。

 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; }
}

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

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