-1

I have the following Json snippet:

{
  "lastUpdated": "2020-08-10T02:59:18+00:00",
  "providerName": "Some Provider",
  "language": "en-US",
  "movies": [
    {
    }
   ]
}

And these proposed class definitions:

[Serializable]

    public class JfoRoot
    {
        public JfoRoot()
        {
        }
    
        public string lastUpdated { get; set; }

        public string providerName { get; set; }

        public string language { get; set; }

    }

[Serializable]
    public class JsonFeedObject
    {        
        public JsonFeedObject()
        {
        }
        
        public JfoRoot jforoot { get; set; }
        
        public MovieObject[] movies { get; set; }
    }    

I'd like to deserialize the Json using:

jfo = JsonConvert.DeserializeObject<JsonFeedObject>(File.ReadAllText(path), jsonSerializerSettings);

Using the above, I'd like to deserialize the first three Json fields into the JfoRoot class. I tried using several approaches that included using [JsonConstructor] and providing a JsonConverter after reading the post Using Newtonsoft.Json with nested custom classes.

Nothing worked. The JfoRoot class was 'null' after every attempt I made. I feel I'm missing something obvious. Or, maybe this can't be done. Can someone shed some light if this is at all possible?

rrirower
  • 4,338
  • 4
  • 27
  • 45
  • What do you mean by "nothing worked"? How didn't it work? If you create a `JsonConverter` and apply it to your `jforoot` property within the `JsonFeedObject` class, you can instantiate the object within the `JsonConverter` and set the properties you need. – Jesse Aug 17 '22 at 19:02
  • https://idownvotedbecau.se/beingunresponsive – Jesse Aug 22 '22 at 16:11

2 Answers2

0

The object you are trying to materialize from the JSON, doesn't match the JSON object. If you moved all of the properties from JfoRoot to the JsonFeedObject, then this would deserialize correctly

public class JsonFeedObject
{
    public JsonFeedObject()
    {
    }

    public string lastUpdated { get; set; } = default!;

    public string providerName { get; set; } = default!;

    public string language { get; set; } = default!;

    public MovieObject[] movies { get; set; } = default!;
}

Then calling

var json = File.ReadAllText(path);
var result = JsonConvert.DeserializeObject<JsonFeedObject>(json);

results in

[14:52:39 INF] {"lastUpdated": "2020-08-10T02:59:18+00:00", "providerName": "Some Provider", "language": "en-US", "movies": [{"$type": "MovieObject"}], "$type": "JsonFeedObject"}

To deserialize them to a sub object I had to add a constructor with the specific properties

public class JfoRoot
{
    public JfoRoot()
    {
    }

    public string lastUpdated { get; set; } = default!;

    public string providerName { get; set; } = default!;

    public string language { get; set; } = default!;
}

public class JsonFeedObject
{
    public JsonFeedObject(string lastUpdated, string providerName, string language, MovieObject[] movies)
    {
        this.jfoRoot = new JfoRoot
        {
            lastUpdated = lastUpdated, 
            providerName = providerName, 
            language = language
        };

        this.movies = movies;
    }

    public JfoRoot jfoRoot { get; set; } = default!;

    public MovieObject[] movies { get; set; } = default!;
}
var json = File.ReadAllText(path);
var result = JsonConvert.DeserializeObject<JsonFeedObject>(json);

resulting in

[15:21:15 INF] {"jfoRoot": {"lastUpdated": "2020-08-10T02:59:18+00:00", "providerName": "Some Provider", "language": "en-US", "$type": "JfoRoot"}, "movies": [{"$type": "MovieObject"}], "$type": "JsonFeedObject"}
wwd
  • 310
  • 1
  • 9
  • 1
    Moving these properties to the base class does not fit the OP's only mentioned requirement which was: *"Using the above, I'd like to deserialize the first three Json fields into the JfoRoot class."*. – Jesse Aug 17 '22 at 19:03
  • @wwd I'm aware that moving those fields into the base class works. In fact, that's how I had coded it originally. But, I now have a new requirement to separate it out into an additional class. – rrirower Aug 17 '22 at 19:09
  • Give me just a minute. – wwd Aug 17 '22 at 19:16
0

I was able to resolve this with a redesign of the classes I use. Rather than using:

[Serializable]
    public class JsonFeedObject
    {        
        public JsonFeedObject()
        {
        }
        
        public JfoRoot jforoot { get; set; }
        
        public MovieObject[] movies { get; set; }
    }    

I switched to:

public class JsonFeedObject : JfoRoot

It's such a simple change and it works to provide all deserialized fields.

rrirower
  • 4,338
  • 4
  • 27
  • 45