Added support for quoted keys

https://github.com/toml-lang/toml/pull/283
This commit is contained in:
moandji.ezana 2015-01-14 09:46:36 +02:00
parent 98701694c4
commit db950ab054
5 changed files with 117 additions and 5 deletions

View file

@ -51,6 +51,9 @@ name = "Mwanji Ezana"
[address]
street = "123 A Street"
city = "AnyVille"
[contacts]
"email address" = me@example.com
````
````java
@ -62,6 +65,7 @@ class Address {
class User {
String name;
Address address;
Map<String, Object> contacts;
}
````
@ -70,10 +74,13 @@ User user = new Toml().parse(tomlFile).to(User.class);
assert user.name.equals("Mwanji Ezana");
assert user.address.street.equals("123 A Street");
assert user.contacts.get("\"email address\"").equals("me@example.com");
````
Any keys not found in both the TOML and the class are ignored. Fields may be private.
Quoted keys cannot be mapped directly to a Java object, but they can be used as keys within a `Map`.
All TOML primitives can be mapped, as well as a number of Java-specific types:
* A TOML Number can be converted to any primitive type (or the wrapper equivalent), `BigInteger` or `BigDecimal`
@ -102,8 +109,11 @@ You can also navigate values within a table with a compound key of the form `tab
Non-existent keys return null.
When retrieving quoted keys, the quotes must be used and the key must be spelled exactly the same way, including whitespace.
````
title = "TOML Example"
"sub title" = "Now with quoted keys"
[database]
ports = [ 8001, 8001, 8002 ]
@ -136,6 +146,7 @@ title = "TOML Example"
Toml toml = new Toml().parse(getTomlFile());
String title = toml.getString("title");
String subTitle = toml.getString("\"sub title\"");
Boolean enabled = toml.getBoolean("database.enabled");
List<Long> ports = toml.getList("database.ports", Long.class);
String password = toml.getString("database.credentials.password");

View file

@ -0,0 +1,33 @@
package com.moandjiezana.toml;
import java.util.ArrayList;
import java.util.List;
class Keys {
static String[] split(String key) {
List<String> splitKey = new ArrayList<String>();
StringBuilder current = new StringBuilder();
char[] chars = key.toCharArray();
boolean quoted = false;
for (char c : chars) {
if (c == '"') {
quoted = !quoted;
}
if (c != '.' || quoted) {
current.append(c);
} else {
splitKey.add(current.toString());
current = new StringBuilder();
}
}
splitKey.add(current.toString());
return splitKey.toArray(new String[0]);
}
private Keys() {}
}

View file

@ -75,7 +75,7 @@ class Results {
stack.pop();
}
String[] tableParts = tableName.split("\\.");
String[] tableParts = Keys.split(tableName);
for (int i = 0; i < tableParts.length; i++) {
String tablePart = tableParts[i];
Container currentContainer = stack.peek();

View file

@ -246,13 +246,14 @@ public class Toml {
@SuppressWarnings("unchecked")
private Object get(String key) {
String[] split = key.split("\\.");
if (values.containsKey(key)) {
return values.get(key);
}
String[] split = Keys.split(key);
Object current = new HashMap<String, Object>(values);
for (int i = 0; i < split.length; i++) {
if (i == 0 && values.containsKey(key)) {
return values.get(key);
}
String keyWithDot = join(Arrays.copyOfRange(split, i, split.length));
if (current instanceof Map && ((Map<String, Object>) current).containsKey(keyWithDot)) {

View file

@ -0,0 +1,67 @@
package com.moandjiezana.toml;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.util.Map;
import org.junit.Test;
public class QuotedKeysTest {
@Test
public void should_accept_quoted_key_for_value() throws Exception {
Toml toml = new Toml().parse("\"127.0.0.1\" = \"localhost\" \n \"character encoding\" = \"UTF-8\" \n \"ʎǝʞ\" = \"value\"");
assertEquals("localhost", toml.getString("\"127.0.0.1\""));
assertEquals("UTF-8", toml.getString("\"character encoding\""));
assertEquals("value", toml.getString("\"ʎǝʞ\""));
}
@Test
public void should_accept_quoted_key_for_table_name() throws Exception {
Toml toml = new Toml().parse("[\"abc def\"]\n val = 1");
assertEquals(1L, toml.getTable("\"abc def\"").getLong("val").longValue());
}
@Test
public void should_accept_partially_quoted_table_name() throws Exception {
Toml toml = new Toml().parse("[dog.\"tater.man\"] \n type = \"pug0\" \n[dog.tater] \n type = \"pug1\"\n[dog.tater.man] \n type = \"pug2\"");
Toml dogs = toml.getTable("dog");
assertEquals("pug0", dogs.getTable("\"tater.man\"").getString("type"));
assertEquals("pug1", dogs.getTable("tater").getString("type"));
assertEquals("pug2", dogs.getTable("tater").getTable("man").getString("type"));
assertEquals("pug0", toml.getString("dog.\"tater.man\".type"));
assertEquals("pug2", toml.getString("dog.tater.man.type"));
}
@Test
@SuppressWarnings("unchecked")
public void should_conserve_quoted_key_in_map() throws Exception {
Toml toml = new Toml().parse("[dog.\"tater.man\"] \n type = \"pug0\" \n[dog.tater] \n type = \"pug1\"\n[dog.tater.man] \n type = \"pug2\"");
Toml dogs = toml.getTable("dog");
Map<String, Map<String, Object>> map = dogs.to(Map.class);
assertEquals("pug0", map.get("\"tater.man\"").get("type"));
assertEquals("pug1", map.get("tater").get("type"));
assertEquals("pug2", ((Map<String, Object>) map.get("tater").get("man")).get("type"));
}
@Test
public void should_convert() throws Exception {
Quoted quoted = new Toml().parse("\"ʎǝʞ\" = \"value\" \n[map] \n \"ʎǝʞ\" = \"value\"").to(Quoted.class);
assertNull(quoted.ʎǝʞ);
assertEquals("value", quoted.map.get("\"ʎǝʞ\""));
}
private static class Quoted {
String ʎǝʞ;
Map<String, Object> map;
}
}