0

I'm working on a game console application that deserialize JSON files that represent differents encounters the player has to deal with.

I have a particular type of encounter named "LootEvent" which contains an Item that the player can gain. Here's the code:

Here's the LootEvent class with its attributes

    public class LootEvent
    {
        public string Name;
        public string Fluff;
        public Item Item;
        public List<LootAction> Actions;
    }

Now here's an example of a JSON file that I want to convert into a LootEvent object:

   {
    "Name" : "A first Loot",
    "Fluff" : "Will you take this item?",
    "Weapon" : {"Name": "Iron Dagger", "Bonus": 1 },
    "Actions" : [{"Text": "Yes", "HasLoot" : true},
        {"Text": "No", "HasLoot" : false}]
   }

As you see there is no "Item" field it's because the field "Weapon" is a derived class of Item:

Here's the Item class:

    public class Item
    {
        public string Name;
        public int Bonus;
    }

And here's the Weapon class:

public class Weapon : Item
{
}

I have other derived class from Item which are in the same style of the "Weapon" class like an "Armor" or "Potion" class.

Now I use this method to convert my json file:

//the "json" variable is a string that contains all of the JSON file text
JsonConvert.DeserializeObject<LootEvent>(json);

So when I convert the JSON File into a LootEvent, all the fields are passed into the LootEvent object except the Item attribute because there's not an Item field in the JSON but a Weapon or Armor or whatever derived class of Item it is.

My question is: How can I deserialize these derived class?

  • 1
    Can this solve your problem: https://stackoverflow.com/questions/8513042/json-net-serialize-deserialize-derived-types ? – Renat May 22 '19 at 07:44
  • Or maybe not. Just to be clear, the *name* of the `Item` field changes to define the polymorphic type? I.e. there might also be `"Armor" : { "Name": "Mithril", "Bonus": 7 }` instead? – dbc May 22 '19 at 07:49
  • Yes the Item field name determine the polymorphic type – Valus_Paulus May 22 '19 at 07:56
  • 1
    This is not about a derived object, this is about the properties in your json objects not matching the properties in your classes. You will need to use "extra data" (google this in relation to json.net) to deserialize all "leftover" properties into a dictionary and then grab what you need out of it, **or** you can declare the required properties on your C# class and then inspect which one was actually set afterwards (the unset ones will be left at their default, `null`). – Lasse V. Karlsen May 22 '19 at 08:14
  • Let me rephrase. You can use custom converters or similar to handle the fact that you want to deserialize into a `Weapon` instance and store it in the `Item` property, but not to handle the fact that you want to deserialize a json property named `Weapon` into a C# property named `Item` based solely on the fact that the *type* of `Weapon` is an `Item`. You will need to handle this oddity yourself. – Lasse V. Karlsen May 22 '19 at 08:16
  • 1
    I used the second method you propose. It's maybe not the "prettiest" but it's the most simple one and it works, thanks ^^ – Valus_Paulus May 22 '19 at 09:15

1 Answers1

0

Use this JsonKnownTypes, it's very similar way to use, it just adddiscriminator to json. But you also need to use that for serialization or if it is external you need to find some property to define what class serializator need to use.

[JsonConverter(typeof(JsonKnownTypeConverter<BaseClass>))]
[JsonDiscriminator(Name = "Name")]
[JsonKnownType(typeof(Base), "Some item")]
[JsonKnownType(typeof(Derived), "weapon")]
public class Item
{
    public string Name;
    public int Bonus;
}
public class Weapon : Item
{
}
Dmitry
  • 192
  • 1
  • 3