0

I am using the Json namespace provided by .NET, not the Newtonsoft one. I have a piece of code:

            string text;
            text = File.ReadAllText(EntityDirectory + @"\Json\AbilityTemplates.json");
            foreach (AbilityTemplate template in JsonSerializer.Deserialize<List<AbilityTemplate>>(text)) {
                loaderInterface.AddAbilityTemplate(template);
            }

When the code run to the JsonSerializer.Deserialize, an execption was thrown.

System.Text.Json.JsonException: 'The JSON value could not be converted to System.Collections.Generic.List`1[Enigma.Game.AbilityTemplate]. Path: $ | LineNumber: 0 | BytePositionInLine: 1.'

This is the Json text that I have:

{
  {
    "ID": "StandardShot",
    "Price": "10",
    "Size": "1",
    "Rarity": "Common",
    "AbilityEffectFactory": "StandardShotEffectFactory"
  },
  {
    "ID": "SelfDestructSingleDamage",
    "Price": "0",
    "Size": "0",
    "Rarity": "NotForPlayer",
    "AbilityEffectFactory": "SelfDestructSingleDamageEffectFactory"
  }
}

I wrote a constructor with JsonConstructor Attribute, but seems like it didn't work:

        public AbilityTemplate(string id, int price, int size, Rarity rarity, AbilityEffectFactory abilityEffectFactory) {
            Id = id;
            Price = price;
            Size = size;
            Rarity = rarity;
            AbilityEffectFactory = abilityEffectFactory;
        }

        [JsonConstructor]
        public AbilityTemplate(string id, int price, int size, Rarity rarity, string abilityEffectFactory) : this(id, price, size, rarity, AbilityEffectFactory.Dictionary[abilityEffectFactory]) { }

Rarity is an enum type.

————————Edit——————————

I change the brackets from {} to [],and also made the fields in json text exactly match the parameters name, but it still didn't work. This is my new Json text:

[
  {
    "id": "StandardShot",
    "price": "10",
    "size": "1",
    "rarity": "Common",
    "abilityEffectFactory": "StandardShotEffectFactory"
  },
  {
    "id": "SelfDestructSingleDamage",
    "price": "0",
    "size": "0",
    "rarity": "NotForPlayer",
    "abilityEffectFactory": "SelfDestructSingleDamageEffectFactory"
  }
]

System.InvalidOperationException: 'Each parameter in the deserialization constructor on type 'Enigma.Game.AbilityTemplate' must bind to an object property or field on deserialization. Each parameter name must match with a property or field on the object. The match can be case-insensitive.'

dbc
  • 104,963
  • 20
  • 228
  • 340
martinrhan
  • 362
  • 1
  • 18
  • 2
    Replace the first pair of '{ }' with "[ ]" To indicate, that you have a List/Array – TheTanic Nov 17 '21 at 08:41
  • I think you're done now. Simply remove the constructor tagged with `JsonConstructor` attribute and you're good to go. – Persian Brat Nov 18 '21 at 15:03
  • Might you please [edit] your question to share a [mcve]? Do note that System.Text.Json is case-sensitive by default; if your property name is `Id` you may need to set `JsonSerializerOptions.PropertyNameCaseInsensitive = true` as shown in [JsonSerializer.Deserialize fails](https://stackoverflow.com/q/60123376/3744182). You also need tp use `JsonStringEnumConverter` to serialize an enum as a string, see [this answer](https://stackoverflow.com/a/59096114/3744182) to [ASP.NET MVC Core API Serialize Enums to String](https://stackoverflow.com/q/59096102/3744182). – dbc Dec 13 '21 at 17:04

1 Answers1

1

The first problem is in your JSON value. You should start and end an array in your JSON file with [ ] instead of { }. To check the validity of your JSON file you can use an online tools such as https://codebeautify.org/jsonviewer. This website is good for validating and editing JSON files.

After changing your JSON file you can deserialize it very easily. First, you should make a model with the same properties as your JSON file. Be careful, the type of properties should match the ones in JSON file. All keys in your sample JSON file are strings.

For this sample file you should make a model as below:

public class weatherForecastModel
    {
        public string ID { get; set; }
        public string Price { get; set; }
        public string Size { get; set; }
        public string Rarity { get; set; }
        public string AbilityEffectFactory { get; set; }
    }

After that, you can deserialize your JSON to your model with one line of code:

var jsonString = File.ReadAllText(EntityDirectory + @"\Json\AbilityTemplates.json");
var weatherForecast = JsonSerializer.Deserialize<List<weatherForecastModel>>(jsonString);

or, if you use Newtonsoft, you can use :

var res = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonString);
Persian Brat
  • 394
  • 2
  • 13
  • But i want to use the JsonConstructor inorder to get rid of an unnecessary aditional class. – martinrhan Nov 17 '21 at 11:31
  • Ok good. but I think my solution its more readable and simple. I always tray to solve problems with simple solution by attention to KISS principle :) https://en.wikipedia.org/wiki/KISS_principle – Roohallah Azizi Nov 17 '21 at 12:37