-2

I am trying to deserialising a JSON response to C# objects using JSON.net.
I am having issues with converting nested objects to a C# list.
I get the JSON response below.
I want to put all the nodes under variants in a single List<Variant> in C#.
How can I edit my deserialiser so that it can be properly deserialised?

{
  "feature_id": "48808",
  "feature_code": "",
  "company_id": "1",
  "feature_type": "S",
  "parent_id": "0",
  "display_on_product": "Y",
  "display_on_catalog": "N",
  "display_on_header": "N",
  "description": "",
  "lang_code": "nl",
  "prefix": "",
  "suffix": "",
  "categories_path": "30,149,161,218,219,220,221,222,483",
  "full_description": "",
  "status": "A",
  "comparison": "Y",
  "position": "8830",
  "purpose": "find_products",
  "feature_style": "text",
  "filter_style": "checkbox",
  "variants": {
    "61719": {
      "variant_id": "61719",
      "variant": "CEE 230V\\/16A",
      "description": "CEE 230V\\/16A",
      "page_title": "",
      "meta_keywords": "",
      "meta_description": "",
      "lang_code": "nl",
      "feature_id": "48808",
      "url": "",
      "color": "",
      "position": "0",
      "seo_name": null,
      "seo_path": null,
      "image_pair": null
    },
    "61720": {
      "variant_id": "61720",
      "variant": "CEE 400V\\/16A",
      "description": "CEE 400V\\/16A",
      "page_title": "",
      "meta_keywords": "",
      "meta_description": "",
      "lang_code": "nl",
      "feature_id": "48808",
      "url": "",
      "color": "",
      "position": "0",
      "seo_name": null,
      "seo_path": null,
      "image_pair": null
    },
    "61721": {
      "variant_id": "61721",
      "variant": "CEE 400V\\/32A",
      "description": "CEE 400V\\/32A",
      "page_title": "",
      "meta_keywords": "",
      "meta_description": "",
      "lang_code": "nl",
      "feature_id": "48808",
      "url": "",
      "color": "",
      "position": "0",
      "seo_name": null,
      "seo_path": null,
      "image_pair": null
    },
    "61722": {
      "variant_id": "61722",
      "variant": "CEE 400V\\/63A",
      "description": "CEE 400V\\/63A",
      "page_title": "",
      "meta_keywords": "",
      "meta_description": "",
      "lang_code": "nl",
      "feature_id": "48808",
      "url": "",
      "color": "",
      "position": "0",
      "seo_name": null,
      "seo_path": null,
      "image_pair": null
    }
  }
}

C# class:

using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;

namespace CsFeature
{
public partial class Feature
{
    [JsonProperty("feature_id")] public string FeatureId { get; set; }

    [JsonProperty("feature_code")] public string FeatureCode { get; set; }

    [JsonProperty("company_id")] public string CompanyId { get; set; }

    [JsonProperty("feature_type")] public string FeatureType { get; set; }

    [JsonProperty("parent_id")] public string ParentId { get; set; }

    [JsonProperty("display_on_product")] public string DisplayOnProduct { get; set; }

    [JsonProperty("display_on_catalog")] public string DisplayOnCatalog { get; set; }

    [JsonProperty("display_on_header")] public string DisplayOnHeader { get; set; }

    [JsonProperty("description")] public string Description { get; set; }

    [JsonProperty("lang_code")] public string LangCode { get; set; }

    [JsonProperty("prefix")] public string Prefix { get; set; }

    [JsonProperty("suffix")] public string Suffix { get; set; }

    [JsonProperty("categories_path")] public string CategoriesPath { get; set; }

    [JsonProperty("full_description")] public string FullDescription { get; set; }

    [JsonProperty("status")] public string Status { get; set; }

    [JsonProperty("comparison")] public string Comparison { get; set; }

    [JsonProperty("position")] public string Position { get; set; }

    [JsonProperty("variants")] public List<Variant> Variants { get; set; }
}

public class Variant
{
    [JsonProperty("variant_id")] public string VariantId { get; set; }
    [JsonProperty("variant")] public string VariantVariant { get; set; }
    [JsonProperty("description")] public string Description { get; set; }

    [JsonProperty("page_title")] public string PageTitle { get; set; }

    [JsonProperty("meta_keywords")] public string MetaKeywords { get; set; }

    [JsonProperty("meta_description")] public string MetaDescription { get; set; }

    [JsonProperty("lang_code")] public string LangCode { get; set; }

    [JsonProperty("feature_id")] public string FeatureId { get; set; }

    [JsonProperty("url")] public string Url { get; set; }

    [JsonProperty("color")] public string Color { get; set; }

    [JsonProperty("position")] public string Position { get; set; }

    [JsonProperty("seo_name")] public object SeoName { get; set; }

    [JsonProperty("seo_path")] public object SeoPath { get; set; }

    [JsonProperty("image_pair")] public object ImagePair { get; set; }
}

public partial class Feature
{
    public static Feature FromJson(string json)
    {
        return JsonConvert.DeserializeObject<Feature>(json, Converter.Settings);
    }

    public static void HandleDeserializationError(object sender, ErrorEventArgs errorArgs)
    {
        errorArgs.ErrorContext.Handled = true;
    }
}

public static class Serialize
{
    public static string ToJson(this Feature self)
    {
        return JsonConvert.SerializeObject(self, Converter.Settings);
    }
}

public static class Converter
{
    public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
        DateParseHandling = DateParseHandling.None,
        NullValueHandling = NullValueHandling.Ignore,
        DefaultValueHandling = DefaultValueHandling.Ignore,
        Converters =
        {
            new IsoDateTimeConverter {DateTimeStyles = DateTimeStyles.AssumeUniversal}
        },
        Error = Feature.HandleDeserializationError
    };
}
}
Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
Luminai
  • 29
  • 1
  • 1
  • 8
  • 1
    if might work if you define the variants model as an `IList` ? – Eamonn McEvoy Jul 09 '20 at 12:17
  • @EamonnMcEvoy Unfortunately that won't work in my case as when serialising I need it to be a list, not multiple objects. – Luminai Jul 09 '20 at 12:20
  • I answered your question , kindly mark my answer as the answer of your question as it solves your problem. Thank you – LopDev Jul 09 '20 at 12:49
  • I think you will need to deserialise the variants it in 2 steps to get a list of variants. First to a collection of key value pairs, then convert the Variant values to a list. – Eamonn McEvoy Jul 09 '20 at 14:01
  • @EamonnMcEvoy That sounds promising! is there anyway to incorporate that into a custom JsonConvertor so it happens automatically when I call from the deserialisation method? – Luminai Jul 09 '20 at 14:08
  • 1
    Use a `Dictionary` for your `Variants` property. That will allow you to handle the numeric keys. See the linked duplicate question. – Brian Rogers Jul 09 '20 at 15:08

2 Answers2

-1

One approach you could take is to .Parse() the JSON into a dynamic object.

For example:

string jsonString = @"Your JSON String";

dynamic parsedJson = JValue.Parse(jsonString);

After that, you should be able to use LINQ to traverse through the dynamic object and extract your Variant

Sources:

LopDev
  • 823
  • 10
  • 26
mzdv
  • 817
  • 9
  • 17
-1

The below code will solve your problem:

  • Create the main Class that will keep your List:
public class JsonList
{
    public List<MainListKeep> ListToKeep { get; set; }
}
  • Create the Class that defines the type of the items of the JsonList class:
public class MainListKeep
{
   public string feature_id { get; set; }
   public string feature_code { get; set; }
   public string company_id{ get; set; }
   public string feature_type { get; set; }
   public string parent_id{ get; set; }
   ...
   ...
   ...
   ...

   public List<VariantsList> variants{ get; set; }
   
}
  • Create the Class that defines the type of the items of the variants:

public class VariantsList 
{
   public string variant_id { get; set; }
   public string variant { get; set; }
   public string description { get; set; }
   public string page_title { get; set; }
   ...
   ...
   ...
   ...
}
    

And then you deserialize using this:

JsonList jsonList = new JsonList(); 
jsonList = JsonConvert.DeserializeObject<JsonList>(YourJSONContentString);

And then you have all of your JSON Response items in the jsonList object and you can use them as you want.
The names of the variables that are relevant with your code must be the same as you can see above in the classes that I have created.

LopDev
  • 823
  • 10
  • 26
  • See my updated post and the C# class I'm using now, this is the same as what you are trying to do and it results in the Variants list being null after deserialising. – Luminai Jul 09 '20 at 13:29
  • @Luminai, this happens because the variants (titles) are numbers... – LopDev Jul 09 '20 at 13:36
  • Well yes I know, that is the problem I'm trying to solve. Preferably using a custom JsonConvertor or something like it. – Luminai Jul 09 '20 at 13:48