36
votes

Équivalent de Jobject dans System.Text.json

J'ai une classe DTO qui a une propriété de type jobject . Cette classe DTO est envoyée / reçoit sur HTTP entre plusieurs services. Jobject est utilisé car le ExtraitdData n'a pas de propriétés prédéfinies

public class MyDTO
{
    public JObject ExtractedData {get;set;}
}

Je convertit ce projet en .NET 5. Qu'est-ce qui est équivalent à Jobject dans .NET 5? J'essaie d'éviter JSONDOCUMENT parce que (à partir du docs ):

JSONDOCUMENT construit une vue en mémoire des données dans un regroupement amortir. Par conséquent, contrairement à Jobject ou Jarray de Newtonsoft.json, le Le type JSONDocument implémente iDisposable et doit être utilisé à l'intérieur d'un Utilisation du bloc.

Je prévois d'utiliser jsonElement . Est-ce le choix le plus approprié ou existe-t-il un autre type disponible pour contenir JSON en tant qu'objet?


0 commentaires

2 Réponses :


23
votes

dans .net 5 et .net core 3.1 l'équivalent le plus proche de jobject est en effet jsonElement afin que vous puissiez modifier votre DTO comme suit:

public class MyDTO
{
    public JsonElement ExtractedData {get;set;} = JsonExtensions.Null;
}

public static class JsonExtensions
{
    static readonly JsonElement nullElement = CreateNull();

    public static JsonElement Null => nullElement;

    static JsonElement CreateNull()
    {
        using var doc = JsonDocument.Parse("null");
        return doc.RootElement.Clone();
    }
}

Pour vous inquiéter de l'élimination de tout document, en interne, le jsonElementConverter Utilisé par jsonserializer Renvoie un élément non réduit (en clonage l'élément dans .net 5) .

Cependant, la correspondance n'est pas ex Agissez, alors gardez ce qui suit à l'esprit:

  • jsonElement représente toute valeur JSON et correspond donc le plus étroitement à jtoken pas jobject . Comme jsonElement est un struct il n'y a pas de sous-classe correspondant à un objet JSON. Si vous souhaitez contraindre ExtraitdData pour être un objet JSON, vous devrez vérifier cela dans le secteur:

    public class MyDTO
    {
        public JsonElement? ExtractedData {get;set;}
    }
    
  • Puisque jsonElement est une structure, la valeur par défaut n'est pas null . Alors c'est quoi? Il s'avère que default (jsonElement) a valuekind = jsonvaluekind.undfined :

    il n'y a pas de valeur (comme distincte de null).

    Si vous essayez de sérialiser un tel par défaut jsonElement avec jsonSerializer , une exception sera lancée. C'est à dire. Si vous faites simplement

    public class MyDTO
    {
        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
        public JsonElement ExtractedData {get;set;}
    }
    
    • Dans .net 5, vous pouvez appliquer [JSONIGNORE (condition = jsonIgnoreCondition.WhenwritingDefault)] Comme:

      var json = JsonSerializer.Serialize(new MyDTO());
      
    • Dans .NET Core 3.x JSONIGIGNORECONDITION n'existe pas, vous pouvez donc définir ExtraitdData pour être nullable:

      public class MyDTO
      {
          JsonElement extractedData;
      
          public JsonElement ExtractedData
          {
              get => extractedData;
              set
              {
                  if (value.ValueKind != JsonValueKind.Object
                      // && value.ValueKind != JsonValueKind.Null Uncomment if you want to allow null
                      )
                      throw new ArgumentException(string.Format("{0} is not a JSON object type", value.ValueKind));
                  extractedData = value;
              }
          }
      }
      
  • Voir aussi les questions connexes:


  • 0 commentaires

    28
    votes

    en novembre 2021, .net 6 introduit le System.Text.json.nodes Espace de noms qui:

    fournit des types pour gérer un objet de document inscripteur en mémoire modèle (DOM) pour l'accès aléatoire des éléments JSON dans un Vue des données

    Les quatre nouveaux types sont jsonArray , jsonObject , jsonNode et jsonValue . Le type le plus proche de jobject est jsonObject qui offre des fonctionnalités similaires.

    Voir ci-dessous pour quelques exemples:

    public class MyDTO
    {
        public JsonObject ExtractedData {get;set;}
    }
    

    D'autres choses intéressantes qui rendent maintenant en utilisant System.Text.json beaucoup plus facile dans .net6 sont répertoriées ci-dessous.

    Analyse , Créer et manipulation DOM

    string s = obj.ToJsonString();
    
    // write pretty json with WriteIndented
    string s = obj.ToJsonString(new JsonSerializerOptions { WriteIndented = true }));
    

    Si vous avez un jsonElement (peut-être après désérialiser dans dynamique , objet , ou jsonElement ) Vous pouvez appeler créer , vous avez maintenant un objet DOM navigable et écrivable:

    List<Friend> friends = obj["Friends"].AsArray().Deserialize<List<Friend>>();
    

    Vous pouvez ajouter / supprimer les propriétés:

    // select Keys
    List<string> keys = obj.Select(node => node.Key).ToList();
    // filter friends
    var friends = obj["Friends"].AsArray()
                 .Where(n => (int)n.AsObject()["Id"] > 2);
    

    Interroger l'objet en toute sécurité pour une clé particulière en utilisant contientKey et tryGetPropertyValue (qui renvoie un jsonNode ):

    if (obj.ContainsKey("Hobbies"))
        // do stuff
    
    if (obj.TryGetPropertyValue("Hobbies", out JsonNode? node))
        // do stuff with node
    

    Données de projet et de filtre

    Il est possible d'utiliser LINQ pour projeter et filtrer le jsonObject :

    obj.Add("FullName", "Bob Smith");
    bool successfullyRemoved = obj.Remove("Name");
    

    désérialiser JSON

    Il est maintenant facile de désérialiser le JSON ou de désérialiser une partie du JSON. Ceci est utile lorsque nous voulons ne désérialiser JSON partiel de l'objet principal. Pour l'exemple ci-dessus, nous pouvons désérialiser la liste des amis dans une liste générique facilement:

    // create
    JsonObject obj = JsonObject.Create(jsonElement);
    

    désériliser () est une méthode d'extension sur jsonNode .

    sérialiser

    Il est facile de sérialiser le JsonObject en utilisant tojSontring () :

    // parse
    var jsonObj = JsonNode.Parse(jsonString).AsObject();
    

    Dans votre cas particulier, vous pouvez définir jsonObject code > Dans votre dto:

    // create object manually using initializer syntax
    JsonObject obj = new JsonObject
    {
        ["Id"] = 3,
        ["Name"] = "Bob",
        ["DOB"] = new DateTime(2001, 02, 03),
        ["Friends"] = new JsonArray
        {
            new JsonObject 
            {
                ["Id"] = 2,
                ["Name"] = "Smith"
            },
            new JsonObject
            {
                ["Id"] = 4,
                ["Name"] = "Jones"
            } 
        }
    };
    
    // random access to values
    int id = (int)obj["Id"];
    DateTime dob = (DateTime)obj["DOB"];
    string firstFriendName = (string)obj["Friends"][0]["Name"];
    


    0 commentaires