Skip to content
This repository has been archived by the owner on Apr 28, 2020. It is now read-only.

Hack to handle single quotes #18

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Json5.Tests/Stringifying/ObjectTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public void UnquotedPropertyNamesTest()
[TestMethod]
public void SingleQuotedStringPropertyNamesTest()
{
var s = Json5.Stringify(new Json5Object { { "a-b", 1 } });
var s = Json5.Stringify(new Json5Object { { "'a-b'", 1 } });
Copy link
Member

@jordanbtucker jordanbtucker Oct 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point of SingleQuotedStringPropertyNamesTest is to ensure that Stringify puts single quotes around property names that are not ES5 Identifiers.

In the original test, the property name was a-b, but your change makes it 'a-b'—a property name that contains single quotes.

If you ran the original test against your hack, it would fail because {'a-b':1} is not equal to {a-b:1}. Your hack actually outputs invalid JSON5.

Assert.AreEqual("{'a-b':1}", s);
}

Expand Down
17 changes: 14 additions & 3 deletions Json5/Json5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,19 +125,30 @@ private static Json5Value Walk(Json5Container holder, string key, Func<Json5Cont
return transformer(holder, key, value);
}

internal static readonly char doubleQuote = '"';
internal static readonly char singleQuote = '\'';

internal static string QuoteString(string s)
{
int doubleQuotes = 0;
int singleQuotes = 0;
foreach (char c in s)
{
if (c == '"')
if (c == doubleQuote)
doubleQuotes++;
else if (c == '\'')
else if (c == singleQuote)
singleQuotes++;
}

char quote = doubleQuotes >= singleQuotes ? '\'' : '"';
char quote = doubleQuotes >= singleQuotes ? singleQuote : doubleQuote;

// Hack that handles single quoted strings (e.g. 'a-b') by removing the single quotes from start and end
if (s != null && s.Length > 1 && s[0] == singleQuote && s[s.Length - 1] == singleQuote)
{
quote = singleQuote;
s = s.Substring(1, s.Length - 2);
}

return quote + EscapeString(s, quote) + quote;
}

Expand Down
30 changes: 30 additions & 0 deletions Json5/Json5Object.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,39 @@ private string KeyToString(string key)
// This will not always work unless we check for Eof after the Identifier.
// We should probably handle this another way.
if (new Json5Lexer(key).Read().Type == Json5TokenType.Identifier)
{
if (DoesIdentifierNeedDoubleQuotes(key))
{
return Json5.QuoteString(key);
}

return key;
}

return Json5.QuoteString(key);
}

/// <summary>
/// Does the identifier need extra double quotes, Currently used to check if there would be issue with single quotes
/// </summary>
/// <param name="input">String to check</param>
/// <returns>True if needs; False otherwise</returns>
private static bool DoesIdentifierNeedDoubleQuotes(string input)
{
// If input contains single quotes that do not start and end the input, then it needs double quotes
if (input.Contains("'"))
{
// If it starts and ends with single quote, everything is OK
if (input[0] == '\'' && input[input.Length - 1] == '\'')
{
return false;
}

// Otherwise it need double quotes
return true;
}

return false;
}
}
}