2016-09-11 13 views
6

残りのAPIを呼び出すときに得られるjsonレスポンスを解析しようとしています 私が直面している問題は、同じリクエストを行っているにもかかわらず、デシリアライズが毎回機能しないということです。 try.catchはもっと良いものを作っていないので、それを修正する方法を知っている。NewtonSoft json converter "未終端の文字列、期待される区切り文字:"; "

また、私は非常に大きな応答(20+ JSONオブジェクト)プログラム働くことはありませんを解析しようとしていたとき。

を私はGoogleで検索しています私自身の問題ですが、解決策はわかりません。

未終了の文字列予想される区切り文字: "。パス '飲み物[0] .strMeasure4'、3行目、位置720。

は、私が得ているエラーの1つです。決して同じではありません。

using Newtonsoft.Json; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net.Sockets; 
using System.Text; 
using System.Threading.Tasks; 
using ConsoleApplication1; 

namespace TCPclient 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 

     TcpClient client = new TcpClient(); 

     client.Connect("www.thecocktaildb.com", 80); // geen http 
     string request = getRequestCoctail("margarita"); 


     NetworkStream stream = client.GetStream(); 


     byte[] buffer = Encoding.Default.GetBytes(request); 

     stream.Write(buffer, 0, buffer.Length); 
     StringBuilder message = new StringBuilder(); 
     int numberOfBytesRead = 0; 
     byte[] receiveBuffer = new byte[1024]; 

     do 
     { 
      numberOfBytesRead = stream.Read(receiveBuffer, 0, receiveBuffer.Length); 

      message.AppendFormat("{0}", Encoding.ASCII.GetString(receiveBuffer, 0, numberOfBytesRead)); 

     } while (stream.DataAvailable); 


     string response = message.ToString(); 

     //Console.WriteLine("Response: \n" + response); 
     response = response.Substring(response.IndexOf("\r\n\r\n")); 
     try 
     { 
      dynamic jsonData = JsonConvert.DeserializeObject(response); 
      List<Drink> drankjes = new List<Drink>(); 

      for (int i = 0; i < jsonData.drinks.Count; i++) 
      { 

       try 
       { 
        string id = jsonData.drinks[i].idDrink; 
        string drink = jsonData.drinks[i].strDrink; 
        string category = jsonData.drinks[i].strCategory; 
        string instructions = jsonData.drinks[i].strInstructions; 
        string glass = jsonData.drinks[i].strGlass; 
        Console.WriteLine(glass); 
        var d = new Drink(id, drink, category, instructions); 

        drankjes.Add(d); 
       } 
       catch (Exception) 
       { 
        Console.WriteLine("error"); 
       } 

      } 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.Message); 
     } 


     //Console.WriteLine(jsonData.drinks.Count); 


     //Console.WriteLine(jsonData.drinks.Count); get ammount of drinks. 
     Console.ReadKey(); 

    } 
    //www.thecocktaildb.com/api/json/v1/1/lookup.php?i=15679 
    private static string getRequestCoctail(string coctail) 
    { 

     ///api/json/v1/1/search.php?s=margarita 
     return $"GET /api/json/v1/1/search.php?s=godfather HTTP/1.1\r\n" 
       + "Host: www.thecocktaildb.com\r\n\r\n"; 
    } 

    private static string GetMetaDataCocktail(dynamic jsonData) 
    { 

     dynamic drink = jsonData.drinks[0]; 
     return $"DrinkID : {drink.idDrink} \nDrinkName : {drink.strDrink} \nInstructions : {drink.strInstructions}"; 
    } 

    private static Drink GenerateNewDrink(dynamic jsonData) 
    { 
     Console.WriteLine(jsonData.idDrink, jsonData.strDrink, jsonData.strCategory, jsonData.strInstructions); 
     return new Drink(jsonData.idDrink, jsonData.strDrink, jsonData.strCategory, "", jsonData.strInstructions); 

    } 
} 
} 

編集:

私は飲み物クラスを追加しました:

class Drink 
{ 
    public readonly string drinkId; 
    public readonly string strDrink; 
    public readonly string strCategory; 
    public readonly string strInstructions; 
    public readonly string strGlass; 

    public Drink(string drinkId, string strDrink, string strCategory, string strInstructions) 
    { 
     this.drinkId = drinkId; 
     this.strDrink = strDrink; 
     this.strCategory = strCategory; 
     this.strInstructions = strInstructions; 
    } 

    public Drink(string drinkId, string strDrink, string strCategory, string strGlass, string strInstructions) 
    { 
     this.drinkId = drinkId; 
     this.strDrink = strDrink; 
     this.strCategory = strCategory; 
     this.strGlass = strGlass; 
     this.strInstructions = strInstructions; 
    } 
} 
} 

私はそれを試してみました:それは、5回のために良い行ってきましたし、私が得た

http://www.thecocktaildb.com/api/json/v1/1/search.php?s=godfather

このエラー+ jsonは受信しました。 6回目もうまくいきました。

http://pastebin.com/c0d29L0S

(その後ベターフォーマットペースト)

予期端オブジェクトをデシリアライズします。パスは「ドリンク[1] .strIngredient1」、3行目、位置1243

{"drinks":[ 
{"idDrink":"11423", 
"strDrink":"Godfather", 
"strCategory":"Ordinary Drink", 
"strAlcoholic":"Alcoholic", 
"strGlass":"Old-fashioned glass", 
"strInstructions":"Pour ingredients into an old-fashioned glass over ice and serve. (Bourbon may be substituted for scotch, if preferred.)", 
"strDrinkThumb":null, 
"strIngredient1":"Scotch", 
"strIngredient2":"Amaretto", 
"strIngredient3":"", 
"strIngredient4":"", 
"strIngredient5":"", 
"strIngredient6":"", 
"strIngredient7":"", 
"strIngredient8":"", 
"strIngredient9":"", 
"strIngredient10":"", 
"strIngredient11":"", 
"strIngredient12":"", 
"strIngredient13":"", 
"strIngredient14":"", 
"strIngredient15":"", 
"strMeasure1":"1 1\/2 oz ", 
"strMeasure2":"3\/4 oz ", 
"strMeasure3":" ", 
"strMeasure4":" ", 
"strMeasure5":" ", 
"strMeasure6":" ", 
"strMeasure7":" ", 
"strMeasure8":"", 
"strMeasure9":"", 
"strMeasure10":"", 
"strMeasure11":"", 
"strMeasure12":"", 
"strMeasure13":"", 
"strMeasure14":"", 
"strMeasure15":"", 
"dateModified":null 
}, 
{"idDrink":"11538", 
"strDrink":"J. R.'s Godfather", 
"strCategory":"Ordinary Drink", 
"strAlcoholic":"Alcoholic", 
"strGlass":"Old-fashioned glass", 
"strInstructions":"In an old-fashioned glass almost filled with ice cubes, combine both of the ingredients. Stir to mix the flavors.", 
"strDrinkThumb":null, 
"strIngredient1": 

それは今うまくいかない理由を私は理解して、JSONはofcourseの無効であるが、これは私が受け取った応答です。だから私は応答を得るために使用しているコードが間違っている..そうですか?

編集3:

同じ要求、良いJSONレスポンス:

http://pastebin.com/e3WNxz0W

今、プログラムが動作しますが、それはincosistentです。

+0

こんにちは@kevin、私は質問にあなたのjson(何か問題がある)を置くことをお勧めします。 jsonの詳細がなければ問題を見つけるのは難しいです。 – Arthas

+0

Drinkクラスを追加することもできます – silver

+0

エラーを受け取ったときにjsonデータをキャプチャしてみてくださいans show – Steve

答えて

3

私は、実際の問題があると思います:IDisposableオブジェクトとオブジェクトがconstractedされている方法を(私はそれのための素晴らしいjson2csharpツールを使用しました)を使用したときにお勧めしusing文の使用を注意してくださいHTTPレスポンスヘッダーを評価していません。

結果はバッチで送信される可能性が最も高くなります。つまり、転送エンコードは「チャンク」ですが、純粋な読者は最初のチャンクを取得し、それを使用します。これはリクエスト間で変更される可能性があります(直接配送でチャンクされている、キャッシュされていない、またはその逆)。ですから、最後にホイールを再発明しないでください。WebClientを使用してください。

Read up the RFC section 3.6.1:チャンクエンコーディングが一連のチャンク、独自のサイズインジケータと各として 転送するためにメッセージの本文を修正

コーディング3.6.1チャンク転送、 に続いて、エンティティヘッダフィールドを含むOPTIONALトレーラが続きます。この は、 がフルメッセージを受信したことを受信者が確認するために必要な情報である、 と一緒に動的に生成されたコンテンツを転送することを許可します。


あなたはこのような問題に遭遇したら、小さな部分にあなたのコードを分割し、これらの部品は、期待される結果をもたらすかどうかを確認してみてください。

あなたの場合、HTTPダウンロードが不完全であるように見えるので、JSONパーサーがエラーを吐いたことを本当に非難することはできません(有効なので)。

+0

問題は:HTTP 1.1が使用されました。 HTTP 1.0を使用する場合、問題はありません。どうして? HTTP 1.1はチャンクを送信します。 TCPクライアント用の理由は、TCPクライアントを使用してそれを操作する方法を学習する必要がありました。 –

1

私はあなたはJSONは無効と変更した後であると思われる(http://www.thecocktaildb.com/api/json/v1/1/lookup.php?i=15679) 言及したサイトからの値を持っている

using Newtonsoft.Json; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net.Sockets; 
using System.Text; 
using System.Threading.Tasks; 
using NUnit.Framework; 

//using ConsoleApplication1; 

namespace TCPclient 
{ 
    [TestFixture] 

    public class Program 
    { 
     [Test] 
     public void Main1() 
     { 

      string response = GetCoctailString(); 
      try 
      { 
       dynamic jsonData = JsonConvert.DeserializeObject(response); 
       List<Drink> drankjes = new List<Drink>(); 

       for (int i = 0; i < jsonData.drinks.Count; i++) 
       { 

        try 
        { 
         string id = jsonData.drinks[i].idDrink; 
         string drink = jsonData.drinks[i].strDrink; 
         string category = jsonData.drinks[i].strCategory; 
         string instructions = jsonData.drinks[i].strInstructions; 
         string glass = jsonData.drinks[i].strGlass; 
         Console.WriteLine(glass); 
         var d = new Drink(id, drink, category, instructions); 

         drankjes.Add(d); 
        } 
        catch (Exception) 
        { 
         Console.WriteLine("error"); 
        } 
       } 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.Message); 
      } 
      Console.ReadKey(); 
     } 
     private static string GetCoctailString() 
     { 
      return "{ 'drinks':[{'idDrink':'15679','strDrink':'Midori Margarita','strCategory':'Ordinary Drink','strAlcoholic':'Alcoholic','strGlass':'Cocktail glass','strInstructions':'Moisten rim of cocktail glass with lime juice and dip in salt. Shake ingredients together, and pour into glass filled with crushed ice. Option: Mix above ingredients with one cup of ice in blender for a smooth, \"granita\" type drink.','strDrinkThumb':null,'strIngredient1':'Tequila','strIngredient2':'Triple sec','strIngredient3':'Lime juice','strIngredient4':'Midori melon liqueur','strIngredient5':'Salt','strIngredient6':'','strIngredient7':'','strIngredient8':'','strIngredient9':'','strIngredient10':'','strIngredient11':'','strIngredient12':'','strIngredient13':'','strIngredient14':'','strIngredient15':'','strMeasure1':'1 1/2 oz ','strMeasure2':'1/2 oz ','strMeasure3':'1 oz fresh ','strMeasure4':'1/2 oz ','strMeasure5':'\n','strMeasure6':'\n','strMeasure7':'\n','strMeasure8':'\n','strMeasure9':'\n','strMeasure10':'\n','strMeasure11':'','strMeasure12':'','strMeasure13':'','strMeasure14':'','strMeasure15':'','dateModified':null}]}"; 
     } 
    } 
    internal class Drink 
    { 
     public Drink(string idDrink, string strDrink, string strCategory, string strInstructions){} 
     public string idDrink { get; set; } 
     public string strDrink { get; set; } 
     public string strCategory { get; set; } 
     public string empty { get; set; } 
     public string strInstructions { get; set; } 
    } 
} 

次のユニットテストであなたの例外を再現しました\ "グラニタ\"のテキストは、すべて異なる引用符を持っています!

私が作ったマニュアル文字列の変更はちょうどのようなものです:

response = response.Replace("\"", "\\\""); 
+0

私が使用したAPIリクエストは、私のためにうまくいきました。私は同じコード、変更はありません。 –

+0

私は手動で\ "グラニタ\"という文字を変更しました – silver

+0

これは私に例外を与えていない、私はメインのポストを編集しました。それらを確認してください。 –

0

私はいくつかのマイナーな変更を使用してコードを再現したのだが、私の知る限り正常に動作します。

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     RootObject root = new RootObject(); 
     using (WebClient wc = new WebClient()) 
     { 
      var json = wc.DownloadString("http://www.thecocktaildb.com/api/json/v1/1/search.php?s=margarita"); 
      root = JsonConvert.DeserializeObject<RootObject>(json); 
     } 

     Console.WriteLine(root.drinks.Count); 
     Console.ReadLine(); 
    } 
} 

public class Drink 
{ 
    public string idDrink { get; set; } 
    public string strDrink { get; set; } 
    public string strCategory { get; set; } 
    public string strAlcoholic { get; set; } 
    public string strGlass { get; set; } 
    public string strInstructions { get; set; } 
    public object strDrinkThumb { get; set; } 
    public string strIngredient1 { get; set; } 
    public string strIngredient2 { get; set; } 
    public string strIngredient3 { get; set; } 
    public string strIngredient4 { get; set; } 
    public string strIngredient5 { get; set; } 
    public string strIngredient6 { get; set; } 
    public string strIngredient7 { get; set; } 
    public string strIngredient8 { get; set; } 
    public string strIngredient9 { get; set; } 
    public string strIngredient10 { get; set; } 
    public string strIngredient11 { get; set; } 
    public string strIngredient12 { get; set; } 
    public string strIngredient13 { get; set; } 
    public string strIngredient14 { get; set; } 
    public string strIngredient15 { get; set; } 
    public string strMeasure1 { get; set; } 
    public string strMeasure2 { get; set; } 
    public string strMeasure3 { get; set; } 
    public string strMeasure4 { get; set; } 
    public string strMeasure5 { get; set; } 
    public string strMeasure6 { get; set; } 
    public string strMeasure7 { get; set; } 
    public string strMeasure8 { get; set; } 
    public string strMeasure9 { get; set; } 
    public string strMeasure10 { get; set; } 
    public string strMeasure11 { get; set; } 
    public string strMeasure12 { get; set; } 
    public string strMeasure13 { get; set; } 
    public string strMeasure14 { get; set; } 
    public string strMeasure15 { get; set; } 
    public object dateModified { get; set; } 
} 
// used http://json2csharp.com/ to get an object from the json string 
public class RootObject 
{ 
    public List<Drink> drinks { get; set; } 
} 
+0

私は飲み物変数の項目にアクセスしようとします:Console.WriteLine(drinks.drinks.Count); JSONの取得に失敗したか、不完全なため、毎回エラーが1回発生します。 –

+0

私の編集を見てください。結果を保持するために変数を追加しました。解析が完了したら、コンソールに出力します。 – Yoav

+0

コードを3回実行しました。コードで3回目と同じエラーが発生しました。 –

関連する問題