NewtonSoft json转换器"未终止字符串,期望分隔符:";“

本文关键字:quot 期望 分隔符 json 转换器 NewtonSoft 终止 字符串 | 更新日期: 2023-09-27 18:06:28

我试图解析调用rest API时得到的json响应。我面临的问题是,即使我发出相同的请求,反序列化也不是每次都有效。我试了一下就不知道该怎么修了。Catch并没有让任何事情变得更好。

另外,当我试图解析一个非常大的响应(20多个json对象)时,程序永远不会工作。

我自己用谷歌搜索过这个问题,但我不知道解决办法。

无端接的字符串。期望分隔符:"。路径的饮料[0]。strMeasure4',第3行,位置720.

是我得到的错误之一,它永远不会相同。

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;
    }
}
}

我试过了:

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

它运行了5次,然后我得到了这个错误+我收到的json。第六次也很好。

http://pastebin.com/c0d29L0S(更好的格式比下面粘贴)

反序列化对象时意外结束。路径的饮料[1]。

{"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当然是无效的,但这是我收到的响应。所以我用来得到响应的代码是错误的…对吧?

编辑3:

相同请求,良好的JSON响应:

http://pastebin.com/e3WNxz0W

现在程序工作了,但是不一致

NewtonSoft json转换器"未终止字符串,期望分隔符:";“

我猜实际的问题是你没有评估HTTP响应头。

结果很可能是分批发送的,即传输编码是"chunked",但你天真的读者只会得到第一个块并使用它,而不是等待更多。这可能会在请求之间发生变化(例如,直接交付时分块,缓存后分块,反之亦然)。所以最后,不要重新发明轮子,只使用WebClient

阅读RFC章节3.6.1:

3.6.1分块传输编码

分块编码修改消息体以便将其作为一系列块进行传输,每个块都有自己的大小指示符,后面是一个可选的尾部,包含实体头字段。这允许动态生成的内容与控件一起传输接收方验证其是否拥有所需的信息收到完整消息。


当你遇到这样的问题时,试着把你的代码分成更小的部分,并检查这些部分是否交付了预期的结果。

在您的示例中,HTTP下载显然是不完整的,因此您不能真正责怪JSON解析器抛出错误(因为它们是有效的)。

我用下面的单元测试复制了您的异常

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; }
    }
}

我已经从你提到的网站(http://www.thecocktaildb.com/api/json/v1/1/lookup.php?i=15679)的价值似乎JSON是无效的,在将"granita"的文本更改为不同的引号后,一切都工作了!

我所做的手工字符串修改就像:
response = response.Replace("'"", "'''"");

我已经复制了你的代码与一些小的变化,它的工作很好,就我所能看到的。请注意使用using语句,这是使用IDisposable对象和对象构造方式的良好实践(我使用了很棒的json2sharp工具):

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; }
}