反序列化复杂的 JSON 数据

Posted

技术标签:

【中文标题】反序列化复杂的 JSON 数据【英文标题】:Deserializing complex JSON data 【发布时间】:2021-12-03 07:57:52 【问题描述】:

我正在尝试反序列化我从这里得到的一些 json https://www.reddit.com/r/tf2/hot/.json?limit=10&rawjson=1,但所有带有 newtonsoft json.net 的示例都显示为简单的 json 对象。

如何将其反序列化为一个不错的对象?

【问题讨论】:

看起来他们的 api 文档 (reddit.com/dev/api/#section_listings) 根本没有描述响应... 我建议先阅读jcchouinard.com/documentation-on-reddit-apis-json & github.com/reddit-archive/reddit/wiki/JSON 或者reddit.com/r/redditdev/comments/bvd7w5/…,然后与现实世界进行比较... 【参考方案1】:

您必须创建自己的对象并在反序列化中指定对象。

YourNewRootClass result = 
                JsonSerializer.Deserialize<YourNewRootClass>(jsonString);

您可以使用此站点创建一个您需要的 json 格式的虚拟对象:https://json2csharp.com/

更新

用你的例子:

Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);

然后:

// Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse); 
public class LinkFlairRichtext

    public string e  get; set; 
    public string t  get; set; 


public class MediaEmbed



public class RedditVideo

    public int bitrate_kbps  get; set; 
    public string fallback_url  get; set; 
    public int height  get; set; 
    public int width  get; set; 
    public string scrubber_media_url  get; set; 
    public string dash_url  get; set; 
    public int duration  get; set; 
    public string hls_url  get; set; 
    public bool is_gif  get; set; 
    public string transcoding_status  get; set; 


public class SecureMedia

    public RedditVideo reddit_video  get; set; 


public class SecureMediaEmbed



public class AuthorFlairRichtext

    public string e  get; set; 
    public string t  get; set; 
    public string a  get; set; 
    public string u  get; set; 


public class Gildings

    public int gid_1  get; set; 


public class ResizedIcon

    public string url  get; set; 
    public int width  get; set; 
    public int height  get; set; 


public class ResizedStaticIcon

    public string url  get; set; 
    public int width  get; set; 
    public int height  get; set; 


public class AllAwarding

    public int? giver_coin_reward  get; set; 
    public string subreddit_id  get; set; 
    public bool is_new  get; set; 
    public int days_of_drip_extension  get; set; 
    public int coin_price  get; set; 
    public string id  get; set; 
    public int? penny_donate  get; set; 
    public string award_sub_type  get; set; 
    public int coin_reward  get; set; 
    public string icon_url  get; set; 
    public int days_of_premium  get; set; 
    public object tiers_by_required_awardings  get; set; 
    public List<ResizedIcon> resized_icons  get; set; 
    public int icon_width  get; set; 
    public int static_icon_width  get; set; 
    public object start_date  get; set; 
    public bool is_enabled  get; set; 
    public object awardings_required_to_grant_benefits  get; set; 
    public string description  get; set; 
    public object end_date  get; set; 
    public int subreddit_coin_reward  get; set; 
    public int count  get; set; 
    public int static_icon_height  get; set; 
    public string name  get; set; 
    public List<ResizedStaticIcon> resized_static_icons  get; set; 
    public string icon_format  get; set; 
    public int icon_height  get; set; 
    public int? penny_price  get; set; 
    public string award_type  get; set; 
    public string static_icon_url  get; set; 


public class Media

    public RedditVideo reddit_video  get; set; 


public class Source

    public string url  get; set; 
    public int width  get; set; 
    public int height  get; set; 


public class Resolution

    public string url  get; set; 
    public int width  get; set; 
    public int height  get; set; 


public class Variants



public class Image

    public Source source  get; set; 
    public List<Resolution> resolutions  get; set; 
    public Variants variants  get; set; 
    public string id  get; set; 


public class Preview

    public List<Image> images  get; set; 
    public bool enabled  get; set; 


public class P

    public int y  get; set; 
    public int x  get; set; 
    public string u  get; set; 


public class S

    public int y  get; set; 
    public int x  get; set; 
    public string u  get; set; 


public class _34nbvtvyhht71

    public string status  get; set; 
    public string e  get; set; 
    public string m  get; set; 
    public List<P> p  get; set; 
    public S s  get; set; 
    public string id  get; set; 


public class Bec5guvyhht71

    public string status  get; set; 
    public string e  get; set; 
    public string m  get; set; 
    public List<P> p  get; set; 
    public S s  get; set; 
    public string id  get; set; 


public class _6bz9mhnlpet71

    public string status  get; set; 
    public string e  get; set; 
    public string m  get; set; 
    public List<P> p  get; set; 
    public S s  get; set; 
    public string id  get; set; 


public class Mgx8gqrlpet71

    public string status  get; set; 
    public string e  get; set; 
    public string m  get; set; 
    public List<P> p  get; set; 
    public S s  get; set; 
    public string id  get; set; 


public class _4eok02vlpet71

    public string status  get; set; 
    public string e  get; set; 
    public string m  get; set; 
    public List<P> p  get; set; 
    public S s  get; set; 
    public string id  get; set; 


public class _5oj0iz0jqet71

    public string status  get; set; 
    public string e  get; set; 
    public string m  get; set; 
    public List<P> p  get; set; 
    public S s  get; set; 
    public string id  get; set; 


public class _6dih3x0jqet71

    public string status  get; set; 
    public string e  get; set; 
    public string m  get; set; 
    public List<P> p  get; set; 
    public S s  get; set; 
    public string id  get; set; 


public class MediaMetadata

    public _34nbvtvyhht71 _34nbvtvyhht71  get; set; 
    public Bec5guvyhht71 bec5guvyhht71  get; set; 
    public _6bz9mhnlpet71 _6bz9mhnlpet71  get; set; 
    public Mgx8gqrlpet71 mgx8gqrlpet71  get; set; 
    public _4eok02vlpet71 _4eok02vlpet71  get; set; 
    public _5oj0iz0jqet71 _5oj0iz0jqet71  get; set; 
    public _6dih3x0jqet71 _6dih3x0jqet71  get; set; 


public class Item

    public string caption  get; set; 
    public string media_id  get; set; 
    public int id  get; set; 


public class GalleryData

    public List<Item> items  get; set; 


public class Data2

    public object approved_at_utc  get; set; 
    public string subreddit  get; set; 
    public string selftext  get; set; 
    public string author_fullname  get; set; 
    public bool saved  get; set; 
    public object mod_reason_title  get; set; 
    public int gilded  get; set; 
    public bool clicked  get; set; 
    public string title  get; set; 
    public List<LinkFlairRichtext> link_flair_richtext  get; set; 
    public string subreddit_name_prefixed  get; set; 
    public bool hidden  get; set; 
    public int pwls  get; set; 
    public string link_flair_css_class  get; set; 
    public int downs  get; set; 
    public int? thumbnail_height  get; set; 
    public object top_awarded_type  get; set; 
    public bool hide_score  get; set; 
    public string name  get; set; 
    public bool quarantine  get; set; 
    public string link_flair_text_color  get; set; 
    public double upvote_ratio  get; set; 
    public string author_flair_background_color  get; set; 
    public string subreddit_type  get; set; 
    public int ups  get; set; 
    public int total_awards_received  get; set; 
    public MediaEmbed media_embed  get; set; 
    public int? thumbnail_width  get; set; 
    public string author_flair_template_id  get; set; 
    public bool is_original_content  get; set; 
    public List<object> user_reports  get; set; 
    public SecureMedia secure_media  get; set; 
    public bool is_reddit_media_domain  get; set; 
    public bool is_meta  get; set; 
    public object category  get; set; 
    public SecureMediaEmbed secure_media_embed  get; set; 
    public string link_flair_text  get; set; 
    public bool can_mod_post  get; set; 
    public int score  get; set; 
    public object approved_by  get; set; 
    public bool is_created_from_ads_ui  get; set; 
    public bool author_premium  get; set; 
    public string thumbnail  get; set; 
    public object edited  get; set; 
    public string author_flair_css_class  get; set; 
    public List<AuthorFlairRichtext> author_flair_richtext  get; set; 
    public Gildings gildings  get; set; 
    public object content_categories  get; set; 
    public bool is_self  get; set; 
    public object mod_note  get; set; 
    public double created  get; set; 
    public string link_flair_type  get; set; 
    public int wls  get; set; 
    public object removed_by_category  get; set; 
    public object banned_by  get; set; 
    public string author_flair_type  get; set; 
    public string domain  get; set; 
    public bool allow_live_comments  get; set; 
    public string selftext_html  get; set; 
    public object likes  get; set; 
    public object suggested_sort  get; set; 
    public object banned_at_utc  get; set; 
    public object view_count  get; set; 
    public bool archived  get; set; 
    public bool no_follow  get; set; 
    public bool is_crosspostable  get; set; 
    public bool pinned  get; set; 
    public bool over_18  get; set; 
    public List<AllAwarding> all_awardings  get; set; 
    public List<object> awarders  get; set; 
    public bool media_only  get; set; 
    public string link_flair_template_id  get; set; 
    public bool can_gild  get; set; 
    public bool spoiler  get; set; 
    public bool locked  get; set; 
    public string author_flair_text  get; set; 
    public List<object> treatment_tags  get; set; 
    public bool visited  get; set; 
    public object removed_by  get; set; 
    public object num_reports  get; set; 
    public object distinguished  get; set; 
    public string subreddit_id  get; set; 
    public bool author_is_blocked  get; set; 
    public object mod_reason_by  get; set; 
    public object removal_reason  get; set; 
    public string link_flair_background_color  get; set; 
    public string id  get; set; 
    public bool is_robot_indexable  get; set; 
    public object report_reasons  get; set; 
    public string author  get; set; 
    public object discussion_type  get; set; 
    public int num_comments  get; set; 
    public bool send_replies  get; set; 
    public string whitelist_status  get; set; 
    public bool contest_mode  get; set; 
    public List<object> mod_reports  get; set; 
    public bool author_patreon_flair  get; set; 
    public string author_flair_text_color  get; set; 
    public string permalink  get; set; 
    public string parent_whitelist_status  get; set; 
    public bool stickied  get; set; 
    public string url  get; set; 
    public int subreddit_subscribers  get; set; 
    public double created_utc  get; set; 
    public int num_crossposts  get; set; 
    public Media media  get; set; 
    public bool is_video  get; set; 
    public string post_hint  get; set; 
    public Preview preview  get; set; 
    public string url_overridden_by_dest  get; set; 
    public bool? is_gallery  get; set; 
    public MediaMetadata media_metadata  get; set; 
    public GalleryData gallery_data  get; set; 
    public string after  get; set; 
    public int dist  get; set; 
    public string modhash  get; set; 
    public object geo_filter  get; set; 
    public List<Child> children  get; set; 
    public object before  get; set; 


public class Child

    public string kind  get; set; 
    public Data data  get; set; 


public class Root

    public string kind  get; set; 
    public Data data  get; set; 

【讨论】:

【参考方案2】:

在快速浏览在线可用信息后。哎呀,这种格式很烦人。

我建议您首先定义一个基本类型、每个“种类”的子类和一个 custom converter 来反序列化它们。可能看起来像这样;

public abstract class RedditBase 

public class RedditListing : RedditBase 
    public string Before  get; set; 
    public string After  get; set; 
    public List<RedditBase> Children  get; set; 

public class RedditConverter : JsonConverter<RedditBase>

    public override void WriteJson(JsonWriter writer, RedditBase value, JsonSerializer serializer)
        => throw new NotImplementedException();

    public override RedditBase ReadJson(JsonReader reader, Type objectType, RedditBase existingValue, bool hasExistingValue, JsonSerializer serializer)
    
        var obj = JObject.Load(reader);
        var data = (JObject)obj["data"];

        switch ((string)obj["kind"])
        
            case "Listing":
                
                    var list = new RedditListing();
                    serializer.Populate(data.CreateReader(), list);
                    return list;
                
            default:
                throw new NotImplementedException();
        
    

【讨论】:

是的,哎呀哎呀 lmao

以上是关于反序列化复杂的 JSON 数据的主要内容,如果未能解决你的问题,请参考以下文章

使用 Alamofire 和 Swift 3 反序列化复杂的 JSON

JSON序列化

使用 C# 反序列化复杂的嵌套 JSON

在 C# 中反序列化复杂对象

如何在 C# .NET 中反序列化复杂的 JSON 对象?

如何正确使用javascript反序列化将json字符串转换为复杂对象?