ServiceStack.Text.JsonObject.Parse vs. NewtonSoft.

2019-06-26 07:06发布

问题:

I'd like to try ServiceStack's json parsing, but I've already figured out how to do something I need via Newtonsoft. Can this same thing by done via ServiceStack?

I've tried with the commented out code but it gives exceptions, see below for exception details.

Thanks!

Josh

    [Test]
    public void TranslateFromGitHubToCommitMessage()
    {
        const string json =
@"
{
'commits': 
[
    {
      'author': {
        'email': 'dev@null.org',
        'name': 'The Null Developer'
      },
      'message': 'okay i give in'
    },
    {
      'author': {
        'email': 'author@github.com',
        'name': 'Doc U. Mentation'
      },
      'message': 'Updating the docs, that\'s my job'
    },
    {
      'author': {
        'email': 'author@github.com',
        'name': 'Doc U. Mentation'
      },
      'message': 'Oops, typos'
    }
]
}
";
        dynamic root = JObject.Parse(json);
        //dynamic root = ServiceStack.Text.JsonSerializer.DeserializeFromString<JsonObject>(json);
        //dynamic root = ServiceStack.Text.JsonObject.Parse(json);

        var summaries = new List<string>();

        foreach (var commit in root.commits)
        {
            var author = commit.author;
            var message = commit.message;
            summaries.Add(string.Format("{0} <{1}>: {2}", author.name, author.email, message));
        }            

        const string expected1 = "The Null Developer <dev@null.org>: okay i give in";
        const string expected2 = "Doc U. Mentation <author@github.com>: Updating the docs, that's my job";
        const string expected3 = "Doc U. Mentation <author@github.com>: Oops, typos";

        Assert.AreEqual(3, summaries.Count);
        Assert.AreEqual(expected1, summaries[0]);
        Assert.AreEqual(expected2, summaries[1]);
        Assert.AreEqual(expected3, summaries[2]);
    }

Exceptions Detail

When using the first commented out line:

dynamic root = ServiceStack.Text.JsonSerializer.DeserializeFromString<JsonObject>(json);

This exception occurs when the method is called.

NullReferenceException:

at ServiceStack.Text.Common.DeserializeListWithElements`2.ParseGenericList(String value, Type      createListType, ParseStringDelegate parseFn)
at ServiceStack.Text.Common.DeserializeEnumerable`2.<>c__DisplayClass3.<GetParseFn>b__0(String value)
at ServiceStack.Text.Common.DeserializeSpecializedCollections`2.<>c__DisplayClass7.  <GetGenericEnumerableParseFn>b__6(String x)
at ServiceStack.Text.Json.JsonReader`1.Parse(String value)
at ServiceStack.Text.JsonSerializer.DeserializeFromString[T](String value)
at GitHubCommitAttemptTranslator.Tests.GitHubCommitAttemptTranslatorTests.TranslateFromGitHubToCommitMessage()

And, the second:

dynamic root = ServiceStack.Text.JsonObject.Parse(json);

var summaries = new List<string>();

foreach (var commit in root.commits) // <-- Happens here

'ServiceStack.Text.JsonObject' does not contain a definition for 'commits'

Note: the message is 'string' does not contain a definition for 'commits' if I use code from line one, but change the type to or to instead of

at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at GitHubCommitAttemptTranslator.Tests.GitHubCommitAttemptTranslatorTests.TranslateFromGitHubToCommitMessage()

After using DynamicJson from .NET 4.0 ServiceStack

Referring to mythz's comment: This test case works, but if I modify it like below:

var dog = new { Name = "Spot", Parts = new { Part1 = "black", Part2 = "gray" }, Arr = new [] { "one", "two", "three"} };
var json = DynamicJson.Serialize(dog);
var deserialized = DynamicJson.Deserialize(json);

Then, deserialized.Name and Parts are fine, but Arr is of type string.

Also:

If I use ' quotes it doesn't appear to work. Is that normal? json2 works (to the degree that Arr is also still a string), but json3 does not work at all. It just returns

Immediate Window:

deserialized = DynamicJson.Deserialize(json3);
{}
base {System.Dynamic.DynamicObject}: {}
_hash: Count = 1

----- code: -----
        var json2 =
            @"
        {
          ""Name"": ""Spot"",
          ""Parts"": {
            ""Part1"": ""black"",
            ""Part2"": ""gray""
          },
          ""Arr"": [
            ""one"",
            ""two"",
            ""three""
          ]
        }";

        var json3 =
            @"
        {
          'Name': 'Spot',
          'Parts': {
            'Part1': 'black',
            'Part2': 'gray'
          },
          'Arr': [
            'one',
            'two',
            'three'
          ]
        }";

        var deserialized = DynamicJson.Deserialize(json1);            

回答1:

ServiceStack's JSON Serializer also supports dynamic parsing, see examples of how to parse GitHub's JSON in the Dynamic JSON section of the wiki page.