2016-04-10 10 views
1

JSONの外部ノードを削除する必要があります。JObject.SelectToken .NETに相当する

{ 
    app: { 
     ... 
    } 
} 

外側のノードを削除する方法上の任意のアイデア、私たちは(.NET Frameworkのツールのみ、JSON.NETを使用してなしのみ

{ 
    ... 
} 

を得る:だから例は以下のようになりますC#)。私が使用Json.NETで

JObject.Parse(json).SelectToken("app").ToString(); 

を代替的に、DataContractJsonSerializerの任意の構成を、デシリアライズ時にルートを無視するようにも機能するであろう。私は今desrializationを行う方法は、次のとおりです。ルートオブジェクトのプロパティ名は、ケースにケースと異なる可能性があること

protected T DeserializeJsonString<T>(string jsonString) 
     { 
      T tempObject = default(T); 

      using (var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(jsonString))) 
      { 
       var serializer = new DataContractJsonSerializer(typeof(T)); 
       tempObject = (T)serializer.ReadObject(memoryStream); 
      } 

      return tempObject; 
     } 

注意。例えば、それは"transaction"とすることができる。

ありがとうございます。

+0

あなたのルートオブジェクトは常にプロパティとして「app」を持っていますか?それとも他のプロパティもサポートする必要がありますか? – rene

+0

は異なる場合があります。たとえば、「トランザクション」 – Vlad

+0

の場合は、JSON.NETを使用できません。それは長年の標準JSONシリアライゼーションライブラリとなりました.ASP.NET WebAPIは内部的にそれを使用しています。組み込みのフレームワークJSONシリアライザは古くなっており、JSON.NETよりも機能が少なくて済むことがあります。 –

答えて

2

.Netに組み込まれているSelectTokenに相当するものはありません。しかし、単純に外側のルートノードをアンラップし、ノード名を事前に知りたくない場合は、次のオプションがあります。あなたのルートオブジェクトは、複数のプロパティが含まれている場合、あなたがデシリアライズすることができないことを

protected T DeserializeNestedJsonString<T>(string jsonString) 
{ 
    using (var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(jsonString))) 
    { 
     var serializer = new DataContractJsonSerializer(typeof(Dictionary<string, T>)); 
     serializer.UseSimpleDictionaryFormat = true; 
     var dictionary = (Dictionary<string, T>)serializer.ReadObject(memoryStream); 
     if (dictionary == null || dictionary.Count == 0) 
      return default(T); 
     else if (dictionary.Count == 1) 
      return dictionary.Values.Single(); 
     else 
     { 
      throw new InvalidOperationException("Root object has too many properties"); 
     } 
    } 
} 

注:純4.5以降を使用している場合

  1. 、あなたはDictionary<string, T>DataContractJsonSerializer.UseSimpleDictionaryFormat = trueとにデシリアライズすることができますDictionary<TKey, TValue>に変更すると、このクラスの項目の順序は未定義であるため、最初のプロパティを取得します。データコントラクトシリアライザをサポートしているネットのいずれかのバージョンに

  2. 、あなたは「その後、最初のネストされたに早送り、XmlObjectSerializerからDataContractJsonSerializer継承が実際にJSONを読み込むXmlReaderを作成するJsonReaderWriterFactory.CreateJsonReader()を呼び出すという事実を利用することができます要素 ":(?XmlReaderでJSONをパース)

    protected T DeserializeNestedJsonStringWithReader<T>(string jsonString) 
    { 
        var reader = JsonReaderWriterFactory.CreateJsonReader(Encoding.Unicode.GetBytes(jsonString), System.Xml.XmlDictionaryReaderQuotas.Max); 
        int elementCount = 0; 
    
        while (reader.Read()) 
        { 
         if (reader.NodeType == System.Xml.XmlNodeType.Element) 
          elementCount++; 
         if (elementCount == 2) // At elementCount == 1 there is a synthetic "root" element 
         { 
          var serializer = new DataContractJsonSerializer(typeof(T)); 
          return (T)serializer.ReadObject(reader, false); 
         } 
        } 
        return default(T); 
    } 
    

    この技術は奇妙に見えますが、いくつかの余分な仕事でSelectToken()に似てJSONのためSAX-like parsing機能を作成するには、この考え方を拡張することが可能である必要があり、前方にスキップJSONで目的のプロパティが見つかるまでその値を逆シリアル化します。以下は、使用することができます。例えば

    、というだけで最初のrootプロパティよりも、特定の名前付きプロパティを、選択してデシリアライズするために、:

    public static class DataContractJsonSerializerExtensions 
    { 
        public static T DeserializeNestedJsonProperty<T>(string jsonString, string rootPropertyName) 
        { 
         // Check for count == 2 because there is a synthetic <root> element at the top. 
         Predicate<Stack<string>> match = s => s.Count == 2 && s.Peek() == rootPropertyName; 
         return DeserializeNestedJsonProperties<T>(jsonString, match).FirstOrDefault(); 
        } 
    
        public static IEnumerable<T> DeserializeNestedJsonProperties<T>(string jsonString, Predicate<Stack<string>> match) 
        { 
         DataContractJsonSerializer serializer = null; 
         using (var reader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(jsonString), XmlDictionaryReaderQuotas.Max)) 
         { 
          var stack = new Stack<string>(); 
          while (reader.Read()) 
          { 
           if (reader.NodeType == System.Xml.XmlNodeType.Element) 
           { 
            stack.Push(reader.Name); 
            if (match(stack)) 
            { 
             serializer = serializer ?? new DataContractJsonSerializer(typeof(T)); 
             yield return (T)serializer.ReadObject(reader, false); 
            } 
            if (reader.IsEmptyElement) 
             stack.Pop(); 
           } 
           else if (reader.NodeType == XmlNodeType.EndElement) 
           { 
            stack.Pop(); 
           } 
          } 
         } 
        } 
    } 
    

    はXMLにどのようJsonReaderWriterFactoryマップJSONの詳細については、Mapping Between JSON and XMLを参照してください。