2017-01-13 3 views
0

J'ai un problème avec JsonPath fonctionnant différemment lors du chargement de jeton (.Load) à la fois en utilisant JsonTextReader et en chargeant le JSON entier en utilisant ReadFrom. Voici un exemple: JSON: "[*] personne" Path = Méthode = SelectTokens (chemin)JsonPath avec JsonTextReader: jeton à la fois

[ 
    { 
    "person": { 
     "personid": 123456 
    } 
    }, 
    { 
    "person": { 
     "personid": 798 
    } 
    } 
] 

Lorsque vous utilisez .ReadFrom, il retournera les 2 éléments appropriés. Si j'utilise .Load cependant, cela retournera 0 éléments. Toutefois, si je change le chemin d'accès à "personne", .ReadFrom renvoie 0 éléments tandis que .Load renvoie 2 éléments. Pour corriger, je pourrais changer le chemin afin qu'il enlève jusqu'au premier "." c'est-à-dire path = sous-chaîne (path.index (".") + 1); Cependant, cela ressemble plus à un bidouillage qu'à un correctif approprié. Naturellement, je devrais également m'assurer que le JSON est un tableau, mais dans la plupart de mes cas, ce serait. Finalement, j'essaie d'apprendre à utiliser le chemin JSON avec des tableaux lors du chargement d'un jeton à la fois. Des recommandations?

Full Code

Full JSON

Répondre

1

ce qui se passe dans le code que vous avez lié à est-il lit des jetons jusqu'à ce qu'il rencontre un objet, il charge alors un JToken de cet objet, qui se lit avant la fin de cet objet. Donc, ce que vous finissez avec est un JToken par élément dans la matrice racine. Vous pouvez alors pour chaque appel JToken:

token.SelectTokens("person").OfType<JObject>() 

parce que vous savez la propriété contient un objet.

Cela équivaut à faire "[*].person" JsonPath sur l'ensemble JSON analysé.

J'espère avoir bien compris votre question. Sinon, s'il vous plaît laissez-moi savoir =)

Mise à jour:

Sur la base de vos commentaires, je comprends ce que vous recherchez. Ce que vous pouvez faire est de créer une méthode comme ceci:

public IEnumerable<JToken> GetTokensByPath(TextReader tr, string path) 
{ 
    // do our best to convert the path to a RegEx 
    var regex = new Regex(path.Replace("[*]", @"\[[0-9]*\]")); 
    using (var reader = new JsonTextReader(tr)) 
    { 
     while (reader.Read()) 
     { 
      if (regex.IsMatch(reader.Path)) 
       yield return JToken.Load(reader); 
     } 
    } 
} 

Je suis correspondant le chemin basé sur l'entrée du chemin JSON, mais nous devons essayer de gérer toutes les différentes grammaires de chemin de JSON, au moment je m prend uniquement en charge *. Cette approche sera utile lorsque vous avez un fichier massif, avec un sélecteur de chemin profond JSON, vous garderez le flux ouvert plus longtemps si vous énumérez lentement, mais vous aurez une utilisation de la mémoire crête beaucoup plus faible.

J'espère que cela aide.

+0

Vous avez certainement. Dans votre cas, vous avez modifié le chemin comme je l'ai fait. J'espérais que je serais capable d'utiliser le chemin json en amont (plus proche du lecteur) donc je n'aurais pas à modifier le chemin. Aussi en modifiant le chemin, s'ils m'ont donné [1] .person, je vais devoir gérer le [1] moi-même. Des idées? Merci pour l'aide. –

+0

Découvrez mes dernières modifications – Stuart