首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在C#中反序列化多个json?

如何在C#中反序列化多个json?
EN

Stack Overflow用户
提问于 2019-08-13 13:08:41
回答 3查看 1.1K关注 0票数 1

我正在通过多个json字符串将一些信息加载到我的Xamarin应用程序中。当我运行应用程序时,它会给出以下错误:

Newtonsoft.Json.JsonSerializationException:‘不能将当前JSON对象(例如{“名称”:“值”})反序列化为'System.Collections.Generic.List`1APIPost’类型,因为该类型需要一个JSON数组(例如,1、2、3)才能正确反序列化。要修复此错误,要么将JSON更改为JSON数组(例如,1,2,3),要么将反序列化类型更改为正常的.NET类型(例如,不像整数这样的原始类型,而不是可以从JSON对象反序列化的数组或列表之类的集合类型。还可以将JsonObjectAttribute添加到类型中,以强制它从JSON对象反序列化。路径'postid',第1行,位置9‘

获取json的代码:

代码语言:javascript
复制
HttpClient client = new HttpClient();
var result = await client.GetStringAsync($"{APIConfig.Uri}/post/getPost/{APIConfig.Token}/{User.ID}/{User.Token}");
List<APIPost> response = JsonConvert.DeserializeObject<List<APIPost>>(result);

foreach (APIPost post in response)
{  //Code  }

APIPost类:

代码语言:javascript
复制
class APIPost
{
    public string state { get; set; }
    public string postid { get; set; }
    public string userid { get; set; }
    public string image { get; set; }
    public string captation { get; set; }
    public string location { get; set; }
    public string date { get; set; }
    public string likes { get; set; }
}

这是我得到的json:

代码语言:javascript
复制
{
    "postid": "2",
    "userid": "2",
    "image": "asdasdasd",
    "captation": "asdasd",
    "location": null,
    "date": "2019-07-29 20:24:28",
    "likes": "4"
}{
    "postid": "1",
    "userid": "2",
    "image": "susfdfjsadv",
    "captation": "This is just a test.",
    "location": null,
    "date": "2019-07-29 19:58:04",
    "likes": "2"
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-08-13 13:15:26

问题不在于C#或您正在使用的JSON序列化库。从服务器接收到的JSON是无效的。因此,没有一个标准的JSON解析库能够成功地解析它。您要么需要编写自己的JSON,要么将JSON更正为有效。

一个有效的对象看起来如下:

代码语言:javascript
复制
{
  "postid": "2",
  "userid": "2",
  "image": "asdasdasd",
  "captation": "asdasd",
  "location": null,
  "date": "2019-07-29 20:24:28",
  "likes": "4"
}

一个有效的对象数组如下所示:

代码语言:javascript
复制
[
  {
    "postid": "2",
    "userid": "2",
    "image": "asdasdasd",
    "captation": "asdasd",
    "location": null,
    "date": "2019-07-29 20:24:28",
    "likes": "4"
  },
  {
    "postid": "1",
    "userid": "2",
    "image": "susfdfjsadv",
    "captation": "This is just a test.",
    "location": null,
    "date": "2019-07-29 19:58:04",
    "likes": "2"
  }
]

在同一个结构中没有所谓的“多个JSON”。你要么有一个有效的结构,要么你没有。你当然可以有多个结构,但你不能让它们都像那样混在一起。

总之..。修复服务器端代码以发送有效的响应。

票数 1
EN

Stack Overflow用户

发布于 2019-08-13 13:16:42

你能控制那个json的来源吗?您需要提供如下内容:

代码语言:javascript
复制
[
    {...},
    {...}
]

你会没事的

票数 0
EN

Stack Overflow用户

发布于 2020-10-08 08:01:54

正如@lasse在评论中所说的,服务器应该是固定的,但是有一种方法可以用Newtonsoft.Json来解析这个问题(万一我们处于那种JSON流场景中):

代码语言:javascript
复制
using (var file = new StreamReader(@"D:\Temp\test.json", Encoding.UTF8))
using (var reader = new Newtonsoft.Json.JsonTextReader(file))
{
    reader.SupportMultipleContent = true;

    var serializer = JsonSerializer.CreateDefault();
    
    serializer.Deserialize(reader).Dump();
    while (reader.Read())
        serializer.Deserialize(reader).Dump();
}

如果您不喜欢将依赖项添加到json.net中,那么我就编写了一个非常简单的JSON拆分器:

代码语言:javascript
复制
IEnumerable<string> SplitJsonStream(string jsonString)
{
    IEnumerable<string> splitJsonStreamInner(char? head, string tail, uint braceNestingLevel, bool insideSubString, string acc)
    {
        if (!head.HasValue)
        {
            if (braceNestingLevel != 0)
                throw new ArgumentException("jsonString seems to be invaid");
            yield break;
        }
    
        char? newHead = null;
        string newAcc = null;
        if (!String.IsNullOrEmpty(tail))
        {
            newHead = tail.First();
        }
        if (head.HasValue)
        {
            newAcc = acc + head.Value;
        }
        var newTail = newHead == null ? null : tail.Substring(1);

        if (!insideSubString && head == '"') {
            foreach(var subAcc in splitJsonStreamInner(newHead, newTail, braceNestingLevel, true, newAcc))
                yield return subAcc;
            yield break;
        }
        if (insideSubString)
        {
            if (head == '"')
            {
                foreach (var subAcc in splitJsonStreamInner(newHead, newTail, braceNestingLevel, false, newAcc))
                    yield return subAcc;
                yield break;
            }
            foreach (var subAcc in splitJsonStreamInner(newHead, newTail, braceNestingLevel, insideSubString, newAcc))
                yield return subAcc;
            yield break;
        }

        if (head == '{')
        {
            foreach (var subAcc in splitJsonStreamInner(newHead, newTail, braceNestingLevel + 1, insideSubString, newAcc))
                yield return subAcc;
            yield break;
        }
        else if (head == '}')
        {
            if (braceNestingLevel == 0)
                throw new ArgumentException("jsonString seems to be invalid");
            var newNestingLevel = braceNestingLevel - 1;
            if (newNestingLevel == 0) {
                yield return newAcc;
                newAcc = String.Empty;
            }
            foreach (var subAcc in splitJsonStreamInner(newHead, newTail, newNestingLevel, insideSubString, newAcc))
                yield return subAcc;
            yield break;
        }
        else
        {
            foreach (var subAcc in splitJsonStreamInner(newHead, newTail, braceNestingLevel, insideSubString, newAcc))
                yield return subAcc;
            yield break;
        }
    }

    jsonString = jsonString.Trim();
    if (jsonString == string.Empty)
        yield break;
    if (!jsonString.StartsWith("{"))
        throw new ArgumentException("jsonString should start with {");
    if (!jsonString.EndsWith("}"))
        throw new ArgumentException("jsonString should end with }");

    foreach (var sub in splitJsonStreamInner(jsonString.First(), jsonString.Substring(1), 0, false, String.Empty))
        yield return sub;
}

以上工作的证明是这个单元测试:

代码语言:javascript
复制
[Fact()]
public void JsonSplitterTests()
{
    Assert.Empty(SplitJsonStream(String.Empty));

    Assert.Throws<ArgumentException>(() => SplitJsonStream("x").Count()); // not startswith {
    Assert.Throws<ArgumentException>(() => SplitJsonStream("{x").Count()); // not endswith }

    var fooJson = "{ \"foo\": 1 }";
    var splitted = SplitJsonStream(fooJson);
    Assert.Equal(1, splitted.Count());
    Assert.Equal(fooJson, splitted.ElementAt(0));

    var barJson = "{ \"bar\": 2 }";
    splitted = SplitJsonStream(fooJson + barJson);
    Assert.Equal(2, splitted.Count());
    Assert.Equal(fooJson, splitted.ElementAt(0));
    Assert.Equal(barJson, splitted.ElementAt(1));

    var bazJson = "{ \"baz\": 3 }";
    splitted = SplitJsonStream(fooJson + barJson + bazJson);
    Assert.Equal(3, splitted.Count());
    Assert.Equal(fooJson, splitted.ElementAt(0));
    Assert.Equal(barJson, splitted.ElementAt(1));
    Assert.Equal(bazJson, splitted.ElementAt(2));

    // ends with bad nesting level
    Assert.Throws<ArgumentException>(() => SplitJsonStream("{{x}").Count());
    Assert.Throws<ArgumentException>(() => SplitJsonStream("{x}}").Count());

    // edge case
    Assert.Equal(1, SplitJsonStream("{ \"foo\": \"{\" }").Count());

    //whitespace in front
    Assert.Equal(2, SplitJsonStream("\n{ \"foo\": 1 }{ \"bar\": 2 }").Count());
    Assert.Equal(2, SplitJsonStream("\r\n{ \"foo\": 1 }{ \"bar\": 2 }").Count());
    Assert.Equal(2, SplitJsonStream("\t{ \"foo\": 1 }{ \"bar\": 2 }").Count());
    Assert.Equal(2, SplitJsonStream(" { \"foo\": 1 }{ \"bar\": 2 }").Count());
    //whitespace at the end
    Assert.Equal(2, SplitJsonStream("{ \"foo\": 1 }{ \"bar\": 2 }\n").Count());
    Assert.Equal(2, SplitJsonStream("{ \"foo\": 1 }{ \"bar\": 2 }\r\n").Count());
    Assert.Equal(2, SplitJsonStream("{ \"foo\": 1 }{ \"bar\": 2 }\t").Count());
    Assert.Equal(2, SplitJsonStream("{ \"foo\": 1 }{ \"bar\": 2 } ").Count());
    //whitespace in the middle
    Assert.Equal(2, SplitJsonStream("{ \"foo\": 1 }\n{ \"bar\": 2 }").Count());
    Assert.Equal(2, SplitJsonStream("{ \"foo\": 1 }\r\n{ \"bar\": 2 }").Count());
    Assert.Equal(2, SplitJsonStream("{ \"foo\": 1 }\t{ \"bar\": 2 }").Count());
    Assert.Equal(2, SplitJsonStream("{ \"foo\": 1 } { \"bar\": 2 }").Count());
}
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57478405

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档