Question

I have a test for checking that an item is serialized correctly

public interface IMyJsIdentity
{
    string Forename { get; }
    string Surname { get; }
    string Guid { get; }                 
}

public class MyIdentity : IMyJsIdentity
{
    public string Forename { get; set; }
    public string Surname { get; set; }
    public string Guid { get; set; }
    public int Id { get; set; }
}

[Fact]
public void SerialiseCorrectly()
{
    // Arrange
    MyIdentity identity = new MyIdentity()
    {
        Forename = "forename",
        Surname = "surname",
        Guid = "abcdefghijk"
    };

    // Act
    string result = JsonConvert.SerializeObject(
        identity, 
        new JsonSerializerSettings()
        {
            ContractResolver = new InterfaceContractResolver(typeof(IMyJsIdentity))
        });

    // Assert
    result.Should().Be(
        "{{\"Forename\":\"forename\",\"Surname\":\"surname\",\"Guid\":\"abcdefghijk\"}}"
        );
}

However I get the following error on the test failure

Xunit.Sdk.AssertException: Expected string to be 
"{{\"Forename\":\"forename\",\"Surname\":\"surname\",\"Guid\":\"abcdefghijk\"}}" with a length of 66, but 
"{{\"Forename\":\"forename\",\"Surname\":\"surname\",\"Guid\":\"abcdefghijk\"}}" has a length of 64.

There's clearly something special that Json.net is doing to the string but I can't figure out what.

Weirdly this passes

result.Should().Be(
    String.Format("{{\"Forename\":\"forename\",\"Surname\":\"surname\",\"Guid\":\"abcdefghijk\"}}")
    );

I guess it's not a big deal but I'd like to know why.

Was it helpful?

Solution

I just tested and the value of result is:

{"Forename":"forename","Surname":"surname","Guid":"abcdefghijk","Id":0}

Which will naturally fail against your expected string of:

"{{\"Forename\":\"forename\",\"Surname\":\"surname\",\"Guid\":\"abcdefghijk\"}}"

Using double curly braces is an escape sequence only for format strings used in the String.Format method so that you may include a single brace. From the Composite Formatting MSDN page:

Opening and closing braces are interpreted as starting and ending a format item. Consequently, you must use an escape sequence to display a literal opening brace or closing brace. Specify two opening braces ("{{") in the fixed text to display one opening brace ("{"), or two closing braces ("}}") to display one closing brace ("}").

If you aren't using String.Format, then the double brace will be interpreted literally as two braces as per the C# Specification 2.4.4.5 since it is not an escape character for string literals.

The resultant error message is confusing. I'm not sure if this is because how the debugger is reporting it to the GUI, or an error with how they are formatting their error message (perhaps they are overly aggressive escaping braces for output), or what.

If you change your test to be:

result.Should().Be(
        "{\"Forename\":\"forename\",\"Surname\":\"surname\",\"Guid\":\"abcdefghijk\"}"
        );

Then it will pass I suspect. This is backed up by your additional test using the String.Format call which changes your double braces to single braces. Now, if you intended to have double wrapping braces around your JSON, that's another issue entirely, but I suspect that that isn't your intent.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top