2016-08-25 8 views
0

私は、それ自体がエスケープされたJSON文字列であるプロパティを持つパブリックAPIからJSONオブジェクトを受け取ります。私はNewtonSoft Json.NETを使用して全体のレスポンスをデシリアライズするために、実際のJSONオブジェクト(エスケープ)にこのプロパティを変換するにはどうすればよいJSONオブジェクト内でエスケープされたJSON文字列を変換するにはどうすればよいですか?

{ 
    "responses":[ 
     { 
     "info":"keep \"this\" in a string", 
     "body":"{\"error\":{\"message\":\"Invalid command\",\"type\":\"Exception\",\"code\":123}}" 
     }, 
     { 
     "info":"more \"data\" to keep in a string", 
     "body":"{\"error\":{\"message\":\"Other error\",\"type\":\"Exception\",\"code\":321}}" 
     } 
    ] 
} 

+0

あなたは身体を変換しますかJSONに?そのJSONですでに –

+0

私はNewtonsoft Json.NETを使用してデシリアライズしようとしましたが、クラスに体を変換しようとするとエラーが発生します。'[JSON String]の値を[MyClass]'に変換するエラー。パス 'responses [0] .body'、1行目、641位。 " – Kcoder

+0

編集をチェックしてください。私はそれを修正した –

答えて

0

ここSam I am's answerのオフに基づいて、私が使用可能な解決策があります:

dynamic obj = JsonConvert.DeserializeObject(json); 
foreach (var response in (IEnumerable<dynamic>)obj.responses) 
{ 
    response.body = JsonConvert.DeserializeObject((string)response.body); 
} 
string result = JsonConvert.SerializeObject(obj); 
0
  1. あなたはプロパティを持つ中間のクラスにそれをデシリアライズすることができます:それは適切な型
  2. があなたの先のモデルを表して、あなたのクラスの新しいインスタンスを作成しますに「体」の文字列をデシリアライズstring Body {get; set;}

そのモデルをシリアライズここでは、ダイナミックタイプと匿名オブジェクトでそれを行うプログラムです。

static void Main(string[] args) 
{ 
    var json = File.ReadAllText("JsonFile1.json"); 
    dynamic obj = JsonConvert.DeserializeObject(json); 

    var dest = new 
    { 
     responses = ((IEnumerable<dynamic>)obj.responses).Select(x => new 
     { 
      info = x.info, 
      body = JsonConvert.DeserializeObject((string)x.body) 
     }) 
    }; 

    var destJson = JsonConvert.SerializeObject(dest); 
    File.WriteAllText("JsonFile2.json", destJson); 
} 

また、あなたはちょうどあなたがjosnを再直列化のように感じていない場合は、あなたの目的地のタイプは、代わりに匿名型であるものは何でもの新しいバージョンを構築することができます。

+0

@downvoter私の答えは間違っていますか?私の答えを使うことができない、JSON.Netをすでに使用できるOPのような人ですか? –

+0

私たちはどちらもdownvotedように見えます。私は、JSONをクリーンアップする方法を見つけることを望んでいました。これは、さまざまなAPIレスポンスのクラスを重複させることなく(これはもっと複雑なものの単純な例です)、値を解析するために使用できる一般的なものです。 – Kcoder

+0

@Kcoder編集しました –

1

JSONには、実際に埋め込まれた二重シリアル化されたJSONオブジェクトのリテラル文字列が含まれています("body")。あなたのタイプのいずれかの内部中間string Json代理プロパティを導入することなく、POCO階層にこれをデシリアライズするには、いくつかのオプションがあります。

  1. あなたはLINQ to JSONを使用してJSONを前処理することができ、そのリテラル"body"文字列を置換します解析された同等物:

    var rootToken = JToken.Parse(json); 
        foreach (var token in rootToken.SelectTokens("responses[*].body").ToList().Where(t => t.Type == JTokenType.String)) 
        { 
         token.Replace(JToken.Parse((string)token)); 
        } 
    
        var root = rootToken.ToObject<RootObject>(); 
    
  2. あなたはにリテラルの着信埋め込まれたJSON文字列を解析し、各Bodyオブジェクトに対応するための一般的なPOCO JsonConverterを導入する可能性

    public class EmbeddedLiteralConverter<T> : JsonConverter 
    { 
        public override bool CanConvert(Type objectType) 
        { 
         return typeof(T).IsAssignableFrom(objectType); 
        } 
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
        { 
         if (reader.TokenType == JsonToken.Null) 
          return null; 
         var contract = serializer.ContractResolver.ResolveContract(objectType); 
         if (contract is JsonPrimitiveContract) 
          throw new JsonSerializationException("Invalid type: " + objectType); 
         if (existingValue == null) 
          existingValue = contract.DefaultCreator(); 
         if (reader.TokenType == JsonToken.String) 
         { 
          var json = (string)JToken.Load(reader); 
          var token = JToken.Parse(json); 
          using (var subReader = token.CreateReader()) 
           serializer.Populate(subReader, existingValue); 
         } 
         else 
         { 
          serializer.Populate(reader, existingValue); 
         } 
         return existingValue; 
        } 
    
        public override bool CanWrite { get { return false; } } 
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
        { 
         throw new NotImplementedException(); 
        } 
    } 
    

    は、それが好き使用:10階層が、そのデシリアライズコンバータチェックが入ってくるJSONトークンは文字列であり、そうでない場合かどうかを確認すること

    var root = JsonConvert.DeserializeObject<RootObject>(json, new EmbeddedLiteralConverter<Body>()); 
    

    注、直接デシリアライズ。したがって、コンバータは、"body" JSONが二重シリアル化されていない場合に使用可能になります。テスト目的のために

私はhttp://json2csharp.com/を使用して、次のターゲット・クラスを生成:

public class Error 
{ 
    public string message { get; set; } 
    public string type { get; set; } 
    public int code { get; set; } 
} 

public class Body 
{ 
    public Error error { get; set; } 
} 

public class Respons 
{ 
    public string info { get; set; } 
    public Body body { get; set; } 
} 

public class RootObject 
{ 
    public List<Respons> responses { get; set; } 
} 
関連する問題