2 votes

Désérialiser une chaîne JSON lorsqu'il n'y a pas de nom de champ en c#

Normalement, lorsque j'utilise des API et que je reçois une chaîne Json en retour, je crée simplement une classe adaptée à la chaîne et je la peuple en utilisant newton JsonConvert.DeserializeObject.

Cependant, j'ai maintenant une chaîne Json dans laquelle l'un des champs n'a pas de nom.

{
    "attacks": {
        "114862720": {
            "code": "115dc2b990153c41c33d519b26cc302a",
            "timestamp_started": 1596782220,
            "timestamp_ended": 1596782226,
            "attacker_id": 580816,
            "attacker_name": "chedders",
            "attacker_faction": 32585,
            "attacker_factionname": "Heart of a Pirate",
            "defender_id": 65306,
            "defender_name": "-Clansdancer",
            "defender_faction": 0,
            "defender_factionname": null,
            "result": "Attacked",
            "stealthed": 0,
            "respect_gain": 4.14,
            "chain": 3,
            "modifiers": {
                "fairFight": 3,
                "war": 1,
                "retaliation": 1,
                "groupAttack": 1,
                "overseas": 1,
                "chainBonus": 1
            }
        },
        "114862829": {
            "code": "8bf08c8ceb9b72f05f40235310cd822e",
            "timestamp_started": 1596782339,
            "timestamp_ended": 1596782344,
            "attacker_id": 580816,
            "attacker_name": "chedders",
            "attacker_faction": 32585,
            "attacker_factionname": "Heart of a Pirate",
            "defender_id": 964979,
            "defender_name": "brko21",
            "defender_faction": 0,
            "defender_factionname": null,
            "result": "Attacked",
            "stealthed": 0,
            "respect_gain": 4.11,
            "chain": 4,
            "modifiers": {
                "fairFight": 3,
                "war": 1,
                "retaliation": 1,
                "groupAttack": 1,
                "overseas": 1,
                "chainBonus": 1
            }
        }
    }
}

Après les attaques, il y a un ID qui est unique à chaque entrée. Donc, construire une classe pour cela comme je le ferais normalement ne fonctionnera pas car l'ID est inconnu.

Toute indication sur la manière de désérialiser cette chaîne serait la bienvenue.

1voto

Athanasios Kataras Points 1140

Vous pouvez utiliser la propriété [JsonExtensionData].

Voici l'exemple officiel:

public class DirectoryAccount
{
    // désérialisation normale
    public string DisplayName { get; set; }

    // ces propriétés sont définies dans OnDeserialized
    public string UserName { get; set; }
    public string Domain { get; set; }

    [JsonExtensionData]
    private IDictionary _additionalData;

    [OnDeserialized]
    private void OnDeserialized(StreamingContext context)
    {
        // SAMAccountName n'est pas désérialisé dans une propriété quelconque
        // donc il est ajouté au dictionnaire de données d'extension
        string samAccountName = (string)_additionalData["SAMAccountName"];

        Domain = samAccountName.Split('\\')[0];
        UserName = samAccountName.Split('\\')[1];
    }

    public DirectoryAccount()
    {
        _additionalData = new Dictionary();
    }
}

Donc dans votre méthode OnDeserializing, vous pouvez récupérer les valeurs du dictionnaire et les ajouter à un champ approprié/les caster en liste d'objets, etc.

1voto

Kieran Devlin Points 634

Cela se désérialiserait en un Dictionnaire. Où Attaque est un type que vous définissez avec toutes les propriétés de chaque objet dans le document JSON.

Cet exemple suppose que vous utilisez la bibliothèque JSON de NewtonSoft :

var attaques = JsonConvert.DeserializeObject>(jsonString);

public class Attaque {
    [JsonProperty("code")]
    public string Code { get; set; }

    [JsonProperty("timestamp_started")]
    public long TimestampStarted { get; set; }

    [JsonProperty("timestamp_ended")]
    public long TimestampEnded { get; set; }

    [JsonProperty("attacker_id")]
    public int AttackerId { get; set; }

    [JsonProperty("attacker_name")]
    public string AttackerName { get; set; }

    [JsonProperty("attacker_faction")]
    public int AttackerFaction { get; set; }

    [JsonProperty("attacker_factionname")]
    public string AttackerFactionName { get; set; }

    [JsonProperty("defender_id")]
    public int DefenderId { get; set; }

    [JsonProperty("defender_name")]
    public string DefenderName { get; set; }

    [JsonProperty("defender_faction")]
    public int DefenderFaction { get; set; }

    [JsonProperty("defender_factionname")]
    public string DefenderFactionName { get; set; }

    [JsonProperty("result")]
    public string Result { get; set; }

    [JsonProperty("stealthed")]
    public int Stealthed { get; set; }

    [JsonProperty("respect_gain")]
    public decimal RespectGain { get; set; }

    [JsonProperty("chain")]
    public int Chain { get; set; }

    [JsonProperty("modifiers")]
    public Dictionnaire Modificateurs { get; set; }
}

Cela donne une collection d'identifiants par rapport à un ensemble de champs fortement typés.

var toutesAttaquesParFaction = attaques.Where(x => x.Value.AttackerFaction == 1234);
var attaqueUnique = attaques.Single(x => x.Key == "");

1voto

tmutton Points 1069

Essayer ce convertisseur JSON.

class AttacksConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Attacks[]);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject attacks = serializer.Deserialize(reader);
        Dictionary result = new Dictionary();

        foreach (JProperty property in attacks.Properties())
        {
            string attackKey = property.Name;
            Attacks attackValue = property.Value.ToObject();

            result.Add(attackKey, new AttackDetails()
            {
                Code = attackValue.Code
            });
        }

        return result;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Le code complet peut être trouvé ici: https://github.com/tmutton/StackOverflowQuestion63544325

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X