首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Newtonsoft Converter FromJson -意外令牌

Newtonsoft Converter FromJson -意外令牌
EN

Stack Overflow用户
提问于 2015-04-19 00:01:39
回答 1查看 1.2K关注 0票数 7

我尝试编写JSON反序列化程序已经有一段时间了,但是一直没能找到我的错误。为什么Newtonsoft在反序列化之后告诉我,Unexpected token when deserializing object: StartObject

代码语言:javascript
复制
type ThisFails =
  { a : string * string
    m : Map<string, string> }

type ThisWorks =
  { y : Map<string, string>
    z : string * string }

testCase "failing test - array before object" <| fun _ ->
  let res = deserialise<ThisFails> Serialisation.converters
                                   """{"a":["xyz","zyx"],"m":{}}"""
  Assert.Equal("should be eq to res", { a = "xyz", "zyx"; m = Map.empty }, res)

testCase "passing test - array after object" <| fun _ ->
  let res = deserialise<ThisWorks> Serialisation.converters
                                   """{"y":{},"z":["xyz","zyx"]}"""
  Assert.Equal("should be eq to res", { y = Map.empty; z = "xyz", "zyx" }, res)

主题is the TupleArrayConverter

该转换器的轨迹为:

代码语言:javascript
复制
reading json [Newtonsoft.Json.FSharp.TupleArrayConverter]
  type => System.Tuple`2[System.String,System.String]

value token, pre-deserialise [Newtonsoft.Json.FSharp.TupleArrayConverter]
  path => "a[0]"
  token_type => String

value token, post-deserialise [Newtonsoft.Json.FSharp.TupleArrayConverter]
  path => "a[1]"
  token_type => String

value token, pre-deserialise [Newtonsoft.Json.FSharp.TupleArrayConverter]
  path => "a[1]"
  token_type => String

value token, post-deserialise [Newtonsoft.Json.FSharp.TupleArrayConverter]
  path => "a"
  token_type => EndArray

after EndArray token, returning [Newtonsoft.Json.FSharp.TupleArrayConverter]
  path => "m"
  token_type => PropertyName

在转换器中,我使用了最后一个令牌,即结束数组,正如您在终止用例中看到的那样:

代码语言:javascript
复制
match reader.TokenType with
| JsonToken.EndArray ->
  read JsonToken.EndArray |> req |> ignore
  acc

一开始我使用的是StartArray令牌...

那么:为什么这段代码不能工作?(Newtonsoft.Json 6.0.8)

这是错误:

代码语言:javascript
复制
map tests/failing test - array before object: Exception: Newtonsoft.Json.JsonSerializationException: Unexpected token when deserializing object: StartObject. Path 'm', line 1, position 24.
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ResolvePropertyAndCreatorValues (Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, Newtonsoft.Json.JsonReader reader, System.Type objectType, IDictionary`2& extensionData) [0x00000] in <filename unknown>:0
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters (Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, Newtonsoft.Json.Serialization.ObjectConstructor`1 creator, System.String id) [0x00000] in <filename unknown>:0
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject (Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract objectContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, Newtonsoft.Json.Serialization.JsonProperty containerProperty, System.String id, System.Boolean& createdFromNonDefaultCreator) [0x00000] in <filename unknown>:0
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x00000] in <filename unknown>:0
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) [0x00000] in <filename unknown>:0
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, Boolean checkAdditionalContent) [0x00000] in <filename unknown>:0  (00:00:00.1500996)
1 tests run: 0 passed, 0 ignored, 0 failed, 1 errored (00:00:00.2482623)
EN

回答 1

Stack Overflow用户

发布于 2015-04-28 05:05:40

我一直在和JSON.Net一起调试你的代码。

事实证明,在您使用了失败案例中的EndArray令牌之后,阅读器会指向一个PropertyName令牌,这一切都很好。

然后,在您的转换器完成执行后,JSON.Net将执行此命令。

代码语言:javascript
复制
} while (!exit && reader.Read());

然后,Read()将阅读器移动到下一个令牌,在您失败的情况下,该令牌是StartObject,导致反序列化程序失败。

所以,我不是JSON.Net方面的专家,但是考虑到在JSON.Net中为字符串值提供一个提供程序,我可能不会在转换后让读者前进,这意味着读者仍然指向字符串值。按照同样的思路,当消费一个数组时,让读取器留在数组值的最后一个令牌,即EndArray令牌,这是有意义的。

所以我的建议仅仅是:

代码语言:javascript
复制
match reader.TokenType with
| JsonToken.EndArray ->
//    read JsonToken.EndArray |> req |> ignore

  Logger.debug logger <| fun _ ->
    LogLine.sprintf
      [ "path", reader.Path |> box
        "token_type", reader.TokenType |> box ]
      "after EndArray token, returning"

  acc

这使得我的测试程序:

代码语言:javascript
复制
[<EntryPoint>]
let main argv = 
    let works = deserialize<ThisWorks> """{"y":{},"z":["xyz","zyx"]}"""
    printfn "%A" works

    let fails = deserialize<ThisFails> """{"a":["xyz","zyx"],"m":{}}"""
    printfn "%A" fails

    0

打印

代码语言:javascript
复制
{y = map [];
 z = ("xyz", "zyx");}
{a = ("xyz", "zyx");
 m = map [];}

希望这能帮助你解决这个错误(你可能已经这样做了)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29719613

复制
相关文章

相似问题

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