Skip to content

Commit 50b2f90

Browse files
committed
add support for single quoted strings
see #9
1 parent 38743e1 commit 50b2f90

10 files changed

Lines changed: 120 additions & 14 deletions

File tree

assets/strings2_result.hjson

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
key1: a key in single quotes
3+
"key 2": a key in single quotes
4+
"key \"": a key in single quotes
5+
text:
6+
[
7+
single quoted string
8+
'''You need quotes for escapes'''
9+
" untrimmed "
10+
"untrimmed "
11+
containing " double quotes
12+
containing " double quotes
13+
containing " double quotes
14+
'''"containing more " double quotes"'''
15+
containing ' single quotes
16+
containing ' single quotes
17+
containing ' single quotes
18+
"'containing more ' single quotes'"
19+
"'containing more ' single quotes'"
20+
"\n"
21+
" \n"
22+
"\n \n \n \n"
23+
"\t\n"
24+
]
25+
foo3a: asdf'''
26+
foo3b: "'''asdf"
27+
foo4a: "asdf'''\nasdf"
28+
foo4b: "asdf\n'''asdf"
29+
}

assets/strings2_result.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"key1": "a key in single quotes",
3+
"key 2": "a key in single quotes",
4+
"key \"": "a key in single quotes",
5+
"text": [
6+
"single quoted string",
7+
"You need quotes\tfor escapes",
8+
" untrimmed ",
9+
"untrimmed ",
10+
"containing \" double quotes",
11+
"containing \" double quotes",
12+
"containing \" double quotes",
13+
"\"containing more \" double quotes\"",
14+
"containing ' single quotes",
15+
"containing ' single quotes",
16+
"containing ' single quotes",
17+
"'containing more ' single quotes'",
18+
"'containing more ' single quotes'",
19+
"\n",
20+
" \n",
21+
"\n \n \n \n",
22+
"\t\n"
23+
],
24+
"foo3a": "asdf'''",
25+
"foo3b": "'''asdf",
26+
"foo4a": "asdf'''\nasdf",
27+
"foo4b": "asdf\n'''asdf"
28+
}

assets/strings2_test.hjson

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
# Hjson 3 allows the use of single quotes
3+
4+
'key1': a key in single quotes
5+
'key 2': a key in single quotes
6+
'key "': a key in single quotes
7+
8+
text: [
9+
'single quoted string'
10+
'You need quotes\tfor escapes'
11+
' untrimmed '
12+
'untrimmed '
13+
'containing " double quotes'
14+
'containing \" double quotes'
15+
"containing \" double quotes"
16+
'"containing more " double quotes"'
17+
'containing \' single quotes'
18+
"containing ' single quotes"
19+
"containing \' single quotes"
20+
"'containing more ' single quotes'"
21+
"\'containing more \' single quotes\'"
22+
23+
'\n'
24+
' \n'
25+
'\n \n \n \n'
26+
'\t\n'
27+
]
28+
29+
# escapes/no escape
30+
31+
foo3a: 'asdf\'\'\''
32+
foo3b: '\'\'\'asdf'
33+
34+
foo4a: 'asdf\'\'\'\nasdf'
35+
foo4b: 'asdf\n\'\'\'asdf'
36+
}

assets/testlist.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ pass3_test.json
7171
pass4_test.json
7272
passSingle_test.hjson
7373
stringify1_test.hjson
74+
strings2_test.hjson
7475
strings_test.hjson
7576
trail_test.hjson
7677
stringify/quotes_all_test.hjson
@@ -80,4 +81,4 @@ stringify/quotes_strings_ml_test.json
8081
stringify/quotes_strings_test.hjson
8182
extra/notabs_test.json
8283
extra/root_test.hjson
83-
extra/separator_test.json
84+
extra/separator_test.json

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
apply plugin: 'java'
22

3-
version = '2.1.1'
3+
version = '3.0.0'
44
group = 'org.hjson'
55
description = """Hjson, the Human JSON."""
66

cli/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apply plugin: 'java'
22
apply plugin: 'maven'
33
apply plugin: 'application'
44

5-
version = '2.1.1'
5+
version = '3.0.0'
66
group = 'org.hjson.cli'
77
description = """Hjson CLI"""
88

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
VERSION_NAME=2.1.1
2+
VERSION_NAME=3.0.0
33
VERSION_CODE=0
44
GROUP=org.hjson
55

history.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# hjson-java History
22

3+
- v3.0.0
4+
- add support for single quoted strings
5+
- add option to turn off legacy support for omitting root braces
6+
- HjsonWriter will always emit root braces
37
- v2.1.1
48
- Update ML stringify to match JS
59
- v2.1.0

src/main/org/hjson/HjsonParser.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ JsonValue checkTrailing(JsonValue v) throws ParseException, IOException {
113113

114114
private JsonValue readValue() throws IOException {
115115
switch(current) {
116+
case '\'':
116117
case '"': return readString();
117118
case '[': return readArray();
118119
case '{': return readObject(false);
@@ -130,7 +131,6 @@ private JsonValue readTfnns() throws IOException {
130131
value.append((char)current);
131132
for (;;) {
132133
read();
133-
if (first=='\'' && value.length()==3 && value.toString().equals("'''")) return readMlString();
134134
boolean isEol=current<0 || current=='\r' || current=='\n';
135135
if (isEol || current==',' ||
136136
current=='}' || current==']' ||
@@ -204,7 +204,7 @@ private JsonObject readObject(boolean objectWithoutBraces) throws IOException {
204204
}
205205

206206
private String readName() throws IOException {
207-
if (current=='"') return readStringInternal();
207+
if (current=='"' || current=='\'') return readStringInternal(false);
208208

209209
StringBuilder name=new StringBuilder();
210210
int space=-1, start=index;
@@ -224,7 +224,7 @@ private String readName() throws IOException {
224224
}
225225
}
226226

227-
private JsonValue readMlString() throws IOException {
227+
private String readMlString() throws IOException {
228228

229229
// Parse a multiline string value.
230230
StringBuilder sb=new StringBuilder();
@@ -249,7 +249,7 @@ else if (current=='\'') {
249249
if (triple==3) {
250250
if (sb.charAt(sb.length()-1)=='\n') sb.deleteCharAt(sb.length()-1);
251251

252-
return new JsonString(sb.toString());
252+
return sb.toString();
253253
}
254254
else continue;
255255
}
@@ -279,27 +279,35 @@ private void skipIndent(int indent) throws IOException {
279279
}
280280

281281
private JsonValue readString() throws IOException {
282-
return new JsonString(readStringInternal());
282+
return new JsonString(readStringInternal(true));
283283
}
284284

285-
private String readStringInternal() throws IOException {
285+
private String readStringInternal(boolean allowML) throws IOException {
286+
// callees make sure that (current=='"' || current=='\'')
287+
int exitCh = current;
286288
read();
287289
startCapture();
288-
while (current!='"') {
290+
while (current!=exitCh) {
289291
if (current=='\\') readEscape();
290292
else if (current<0x20) throw expected("valid string character");
291293
else read();
292294
}
293295
String string=endCapture();
294296
read();
295-
return string;
297+
298+
if (allowML && current=='\'' && string.length()==0) {
299+
// ''' indicates a multiline string
300+
read();
301+
return readMlString();
302+
} else return string;
296303
}
297304

298305
private void readEscape() throws IOException {
299306
pauseCapture();
300307
read();
301308
switch(current) {
302309
case '"':
310+
case '\'':
303311
case '/':
304312
case '\\':
305313
captureBuffer.append((char)current);

src/main/org/hjson/HjsonWriter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class HjsonWriter {
3030

3131
private IHjsonDsfProvider[] dsfProviders;
3232

33-
static Pattern needsEscapeName=Pattern.compile("[,\\{\\[\\}\\]\\s:#\"]|//|/\\*|'''");
33+
static Pattern needsEscapeName=Pattern.compile("[,\\{\\[\\}\\]\\s:#\"']|//|/\\*|'''");
3434

3535
public HjsonWriter(HjsonOptions options) {
3636
if (options!=null) {
@@ -124,7 +124,7 @@ void writeString(String value, Writer tw, int level, String separator) throws IO
124124
if (doEscape ||
125125
HjsonParser.isWhiteSpace(left) || HjsonParser.isWhiteSpace(right) ||
126126
left=='"' ||
127-
left=='\'' && left1=='\'' && left2=='\'' ||
127+
left=='\'' ||
128128
left=='#' ||
129129
left=='/' && (left1=='*' || left1=='/') ||
130130
JsonValue.isPunctuatorChar(left) ||

0 commit comments

Comments
 (0)