com.electronwill.nightconfig.core.Config Java Examples

The following examples show how to use com.electronwill.nightconfig.core.Config. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: YamlFormat.java    From night-config with GNU Lesser General Public License v3.0 6 votes vote down vote up
@Override
public boolean supportsType(Class<?> type) {
	return type == null
           || type.isEnum()
           || type == Boolean.class
           || type == String.class
           || type == java.util.Date.class
           || type == java.sql.Date.class
           || type == java.sql.Timestamp.class
           || type == byte[].class
           || type == Object[].class
           || Number.class.isAssignableFrom(type)
           || Set.class.isAssignableFrom(type)
           || List.class.isAssignableFrom(type)
           || Config.class.isAssignableFrom(type);
}
 
Example #2
Source File: ObjectConverter.java    From night-config with GNU Lesser General Public License v3.0 6 votes vote down vote up
/**
 * Converts a collection of objects of the type srcBottomType to a collection of configurations.
 *
 * @param src           the collection of objects, may be nested, source
 * @param srcBottomType the type of objects
 * @param dst           the collection of configs, destination
 * @param parentConfig  the parent configuration, used to create the new configs to put in dst
 */
private void convertObjectsToConfigs(Collection<?> src,
								     Class<?> srcBottomType,
								     Collection<Object> dst,
								     Config parentConfig) {
	for (Object elem : src) {
		if (elem == null) {
			dst.add(null);
		} else if (srcBottomType.isAssignableFrom(elem.getClass())) {
			Config elementConfig = parentConfig.createSubConfig();
			convertToConfig(elem, elem.getClass(), elementConfig);
			dst.add(elementConfig);
		} else if (elem instanceof Collection) {
			ArrayList<Object> subList = new ArrayList<>();
			convertObjectsToConfigs((Collection<?>)elem, srcBottomType, subList, parentConfig);
			subList.trimToSize();
			dst.add(subList);
		} else {
			String elemType = elem.getClass().toString();
			throw new InvalidValueException("Unexpected element of type " + elemType + " in collection of " + srcBottomType);
		}
	}
}
 
Example #3
Source File: ObjectConverterTest.java    From night-config with GNU Lesser General Public License v3.0 6 votes vote down vote up
public MyObjectFinal(int integer, double decimal, String string, List<String> stringList,
						List<SomeObject> objList,
						List<List<SomeObject>> nestedObjList2,
						List<List<List<SomeObject>>> nestedObjList3,
						Config config,
						MyObjectFinal subObject,
						TestEnum enumValue) {
	this.integer = integer;
	this.decimal = decimal;
	this.string = string;
	this.stringList = stringList;
	this.objList = objList;
	this.nestedObjList2 = nestedObjList2;
	this.nestedObjList3 = nestedObjList3;
	this.config = config;
	this.subObject = subObject;
	this.enumValue = enumValue;
}
 
Example #4
Source File: YamlParser.java    From night-config with GNU Lesser General Public License v3.0 6 votes vote down vote up
@Override
public void parse(Reader reader, Config destination, ParsingMode parsingMode) {
	try {
		Map<String, Object> wrappedMap = wrap(yaml.loadAs(reader, Map.class));
		parsingMode.prepareParsing(destination);
		if (parsingMode == ParsingMode.ADD) {
			for (Map.Entry<String, Object> entry : wrappedMap.entrySet()) {
				destination.valueMap().putIfAbsent(entry.getKey(), entry.getValue());
			}
		} else {
			destination.valueMap().putAll(wrappedMap);
		}
	} catch (Exception e) {
		throw new ParsingException("YAML parsing failed", e);
	}
}
 
Example #5
Source File: ConvertedConfig.java    From night-config with GNU Lesser General Public License v3.0 6 votes vote down vote up
@Override
@SuppressWarnings("unchecked")
public Set<Config.Entry> entries() {
	Function<Config.Entry, Config.Entry> readTransfo = entry -> null;/*TODOnew Config.Entry() {
		@Override
		public Object setValue(Object value) {
			return readConversion.apply(entry.setValue(writeConversion.apply(value)));
		}

		@Override
		public String getKey() {
			return entry.getKey();
		}

		@Override
		public <T> T getValue() {
			return (T)readConversion.apply(entry.getValue());
		}
	};*/
	return new TransformingSet<>(config.entries(), readTransfo, o -> null, e -> e);
}
 
Example #6
Source File: ObjectConverterTest.java    From night-config with GNU Lesser General Public License v3.0 6 votes vote down vote up
public MyObjectFinal(int integer, double decimal, String string, List<String> stringList,
						List<SomeObject> objList,
						List<List<SomeObject>> nestedObjList2,
						List<List<List<SomeObject>>> nestedObjList3,
						Config config,
						MyObjectFinal subObject,
						TestEnum enumValue) {
	this.integer = integer;
	this.decimal = decimal;
	this.string = string;
	this.stringList = stringList;
	this.objList = objList;
	this.nestedObjList2 = nestedObjList2;
	this.nestedObjList3 = nestedObjList3;
	this.config = config;
	this.subObject = subObject;
	this.enumValue = enumValue;
}
 
Example #7
Source File: ObjectConverterTest2.java    From night-config with GNU Lesser General Public License v3.0 6 votes vote down vote up
@Test
public void testSupportBasic() {
	ObjectConverter converter = new ObjectConverter();
	Config config = Config.inMemory();
	MyObject object = new MyObject();
	converter.toConfig(object, config);

	System.out.println("MyObject mapped to a SimpleConfig with basic strategy:");
	System.out.println(config);

	assertEquals(object.integer, (int)config.get("integer"));
	assertEquals(object.decimal, (double)config.get("decimal"));
	assertEquals(object.string, config.get("string"));
	assertEquals(object.stringList, config.get("stringList"));
	assertEquals(object.objList.size(), config.<List<?>>get("objList").size());
	assertEquals(object.config, config.get("config"));
	assertTrue(config.get("subObject") instanceof Config);
	Config sub = config.get("subObject");
	assertEquals(object.subObject.integer, (int)sub.get("integer"));
	assertEquals(object.subObject.decimal, (double)sub.get("decimal"));
	assertEquals(object.subObject.string, sub.get("string"));
	assertEquals(object.subObject.stringList, sub.get("stringList"));
	assertEquals(object.subObject.objList.size(), sub.<List<?>>get("objList").size());
	assertNull(sub.get("subObject"));
}
 
Example #8
Source File: ObjectConverterTest2.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Test
public void testSupportAll() {
	ObjectConverter converter = new ObjectConverter();
	Config config = Config.inMemoryUniversal();
	// withUniversalSupport() causes the configuration to accept any type of values without conversion

	MyObject object = new MyObject();
	converter.toConfig(object, config);

	System.out.println("MyObject mapped to a SimpleConfig with support_all strategy:");
	System.out.println(config);

	assertEquals(object.integer, (int)config.get("integer"));
	assertEquals(object.decimal, (double)config.get("decimal"));
	assertSame(object.string, config.get("string"));
	assertSame(object.stringList, config.get("stringList"));
	assertSame(object.objList, config.get("objList"));
	assertSame(object.config, config.get("config"));
	assertSame(object.subObject, config.get("subObject"));

	/*
		@Conversion(CoordinatesConverter.class)
		@Path("infos.coordinates")
		@SpecNotNull
		Coordinates coords = new Coordinates(...);
	 */
	assertNotNull(config.get("infos.coordinates"));
	assertEquals(object.coords.toString(), config.get("infos.coordinates"));
}
 
Example #9
Source File: ObjectConverterTest.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
private void testConfigToObject(Config config, Object object) throws Exception {
	System.out.println("Before: " + object);

	ObjectConverter converter = new ObjectConverter();
	converter.toObject(config, object);

	System.out.println("After: " + object);
}
 
Example #10
Source File: ObjectConverterTest.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Test
public void configToObjectToConfigToObject() throws Exception {
	ObjectConverter converter = new ObjectConverter();
	MyObject object = converter.toObject(config, MyObject::new);
	Config newConfig = Config.inMemory();
	converter.toConfig(object, newConfig);

	MyObject newObject = new MyObject();
	converter.toObject(newConfig, newObject);

	System.out.println("Original config: " + config);
	System.out.println("New config: " + newConfig);
	System.out.println("\nOriginal object: " + object);
	System.out.println("New object: " + object);

       // test the enum values
       assertEquals(TestEnum.A, config.getEnum("enumValue", TestEnum.class));
       assertEquals(TestEnum.C, config.getEnum("subObject.enumValue", TestEnum.class, EnumGetMethod.ORDINAL_OR_NAME));

       // Replace string and integer by enum values in order to compare the configs properly
       // (the object converter should have put enum values in the new config)
       config.set("enumValue", TestEnum.A);
       config.set("subObject.enumValue", TestEnum.C);

       // ensure that the conversion was well done
       assertEquals(config, newConfig, "Invalid conversion");
	assertEquals(object, newObject, "Invalid conversion");
}
 
Example #11
Source File: CheckedConfig.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
private void recursiveCheck(Deque<String> path, Object value) {
	if (value instanceof Config) {
		for (Config.Entry entry : ((Config)value).entries()) {
			path.addLast(entry.getKey());
			recursiveCheck(path, entry.getValue());
			path.removeLast();
		}
	} else {
		String[] arr = (String[])path.toArray();
		checker.checkUpdate(StandardAttributes.VALUE, arr, value, value);
	}
}
 
Example #12
Source File: CheckedConfig.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
/**
 * Creates a new CheckedConfig and checks the existing elements with the checker.
 * @param config the config to use as a data storage
 * @param checker will check the config's data
 */
public CheckedConfig(Config config, ConfigChecker checker) {
	super(config);
	this.checker = checker;

	// The config might already contain some elements and we must be sure that
	// they are all correct
	Deque<String> path = new LinkedList<>();
	config.valueMap().forEach((k, v) -> {
		path.add(k);
		recursiveCheck(path, v);
		path.remove();
	});
}
 
Example #13
Source File: YamlParser.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
private Object wrap(Object value) {
	if (value instanceof Map) {
		Map<String, Object> map = wrap((Map)value);
		return Config.wrap(map, configFormat);
	}
	if (value == null) {
		return NULL_OBJECT;
	}
	return value;
}
 
Example #14
Source File: HoconParser.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Override
public void parse(Reader reader, Config destination, ParsingMode parsingMode) {
	try {
		ConfigObject parsed = ConfigFactory.parseReader(reader, OPTIONS).resolve().root();
		parsingMode.prepareParsing(destination);
		if (destination instanceof CommentedConfig) {
			put(parsed, (CommentedConfig)destination, parsingMode);
		} else {
			put(parsed, destination, parsingMode);
		}
	} catch (Exception e) {
		throw new ParsingException("HOCON parsing failed", e);
	}
}
 
Example #15
Source File: HoconParser.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
private static void put(ConfigObject typesafeConfig, Config destination,
						ParsingMode parsingMode) {
	for (Map.Entry<String, ConfigValue> entry : typesafeConfig.entrySet()) {
		List<String> path = ConfigUtil.splitPath(entry.getKey());
		parsingMode.put(destination, path, unwrap(entry.getValue().unwrapped()));
	}
}
 
Example #16
Source File: JsonFormat.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
/**
 * @return an instance of JsonFormat with a parser that accepts empty inputs and a fancy writer
 */
public static JsonFormat<FancyJsonWriter> emptyTolerantInstance() {
	return new JsonFormat<FancyJsonWriter>() {
		@Override
		public FancyJsonWriter writer() {
			return new FancyJsonWriter();
		}

		@Override
		public ConfigParser<Config> parser() {
			return new JsonParser(this).setEmptyDataAccepted(true);
		}
	};
}
 
Example #17
Source File: ObjectConverter.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
public void toConfig(Class<?> clazz, Config destination) {
	Objects.requireNonNull(destination, "The config must not be null.");
	List<String> annotatedPath = AnnotationUtils.getPath(clazz);
	if (annotatedPath != null) {
		destination = destination.getRaw(annotatedPath);
	}
	convertToConfig(null, clazz, destination);
}
 
Example #18
Source File: ObjectBinderTest.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Test
public void writeToObjectTest() {
	MyObjectFinal subObject = new MyObjectFinal(0, 3.14159265358, "", null, null, null, null, null, null, null);
	MyObjectFinal object = new MyObjectFinal(123, 1.23, "initialV", list2, null, null, null, config2, subObject, TestEnum.C);
	ObjectBinder binder = new ObjectBinder();
	Config config = binder.bind(object);
	config.set("integer", 1234568790);
	config.set("decimal", Math.PI);
	config.set("string", "value");
	config.set("stringList", list1);
	config.set("config", config1);
	config.set("enumValue", "A");
	config.set("subObject.integer", -1);
	config.set("subObject.decimal", 0.5);
	config.set("subObject.string", "Hey!");
	config.set("subObject.stringList", list2);
	config.set("subObject.config", config2);
	config.set("subObject.subObject", null);
	config.set("subObject.enumValue", "B");

	// Checks that the object has been modified according to the config
	assertEquals((int)config.get("integer"), object.integer);
	assertEquals((double)config.get("decimal"), object.decimal);
	assertEquals(config.get("string"), object.string);
	assertEquals(config.get("stringList"), object.stringList);
	assertNull(object.objList);
	assertEquals(config.get("config"), object.config);
	assertEquals(config.getEnum("enumValue", TestEnum.class), object.enumValue);
	assertTrue(config.get("subObject") instanceof Config);

	Config sub = config.get("subObject");
	assertEquals((int)sub.get("integer"), object.subObject.integer);
	assertEquals((double)sub.get("decimal"), object.subObject.decimal);
	assertEquals(sub.get("string"), object.subObject.string);
	assertEquals(sub.get("stringList"), object.subObject.stringList);
	assertEquals(sub.getEnum("enumValue", TestEnum.class), object.subObject.enumValue);
	assertNull(object.subObject.objList);
	assertNull(sub.get("subObject"));
}
 
Example #19
Source File: ObjectConverterTest.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Test
public void configToObjectToConfigToObject() throws Exception {
	ObjectConverter converter = new ObjectConverter();
	MyObject object = converter.toObject(config, MyObject::new);
	Config newConfig = Config.inMemory();
	converter.toConfig(object, newConfig);

	MyObject newObject = new MyObject();
	converter.toObject(newConfig, newObject);

	System.out.println("Original config: " + config);
	System.out.println("New config: " + newConfig);
	System.out.println("\nOriginal object: " + object);
	System.out.println("New object: " + object);

       // test the enum values
       assertEquals(TestEnum.A, config.getEnum("enumValue", TestEnum.class));
       assertEquals(TestEnum.C, config.getEnum("subObject.enumValue", TestEnum.class, EnumGetMethod.ORDINAL_OR_NAME));

       // Replace string and integer by enum values in order to compare the configs properly
       // (the object converter should have put enum values in the new config)
       config.set("enumValue", TestEnum.A);
       config.set("subObject.enumValue", TestEnum.C);

       // ensure that the conversion was well done
       assertEquals(config, newConfig, "Invalid conversion");
	assertEquals(object, newObject, "Invalid conversion");
}
 
Example #20
Source File: JsonConfigTest.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Test
public void testReadEmptyFile() throws IOException {
	File f = new File("tmp.json");
	FileConfig config = FileConfig.of(f);
	config.load();
	config.close();
	Config conf = new JsonParser().parse(f, FileNotFoundAction.THROW_ERROR);
	System.out.println(conf);
	assertTrue(conf.isEmpty());
	System.out.println("tmp.json:\n" + Files.readAllLines(f.toPath()).get(0));
	f.delete();
}
 
Example #21
Source File: ObjectConverter.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
/**
 * Converts an Object to a Config.
 *
 * @param o           the object to convert
 * @param destination the Config where to put the values into
 */
public void toConfig(Object o, Config destination) {
	Objects.requireNonNull(o, "The object must not be null.");
	Objects.requireNonNull(destination, "The config must not be null.");
	Class<?> clazz = o.getClass();
	List<String> annotatedPath = AnnotationUtils.getPath(clazz);
	if (annotatedPath != null) {
		destination = destination.getRaw(annotatedPath);
	}
	convertToConfig(o, clazz, destination);
}
 
Example #22
Source File: TomlParser.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
private void checkContainsOnlySubtables(Config table, List<String> path) {
	for (Object value : table.valueMap().values()) {
		if (!(value instanceof Config)) {
			throw new ParsingException("Table with path " + path + " has been declared twice.");
		}
	}
}
 
Example #23
Source File: ValueWriter.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
/**
 * Writes a value. This method calls the correct writing method based on the value's type.
 */
static void write(Object value, CharacterOutput output, TomlWriter writer) {
	if (value instanceof Config) {
		TableWriter.writeInline((Config)value, output, writer);
	} else if (value instanceof List) {
		List<?> list = (List<?>)value;
		if (!list.isEmpty() && list.get(0) instanceof Config) {// Array of tables
			for (Object table : list) {
				TableWriter.writeInline((Config)table, output, writer);
			}
		} else {// Normal array
			ArrayWriter.write((List<?>)value, output, writer);
		}
	} else if (value instanceof CharSequence) {// String
		writeString(value.toString(), output, writer);
	} else if (value instanceof Enum) {// Enum value
		writeString(((Enum<?>)value).name(), output, writer);
	} else if (value instanceof Temporal) {// Date or DateTime
		TemporalWriter.write((Temporal)value, output);
	} else if (value instanceof Float || value instanceof Double) {// Floating-point number
		double d = ((Number)value).doubleValue();
		if (Double.isNaN(d)) {
			output.write("nan");
		} else if (d == Double.POSITIVE_INFINITY) {
			output.write("+inf");
		} else if (d == Double.NEGATIVE_INFINITY) {
			output.write("-inf");
		} else {
			output.write(value.toString());
		}
	} else if (value instanceof Number || value instanceof Boolean) {
		output.write(value.toString());
	} else if (value == null || value == NULL_OBJECT) {
		throw new WritingException("TOML doesn't support null values");
	} else {
		throw new WritingException("Unsupported value type: " + value.getClass());
	}
}
 
Example #24
Source File: TomlWriterTest.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Test
public void writeToString() {
	Config subConfig = TomlFormat.instance().createConfig();
	subConfig.set("string", "test");
	subConfig.set("dateTime", ZonedDateTime.now());
	subConfig.set("sub", TomlFormat.instance().createConfig());

	List<Config> tableArray = new ArrayList<>();
	tableArray.add(subConfig);
	tableArray.add(subConfig);
	tableArray.add(subConfig);

	Config config = TomlFormat.instance().createConfig();
	config.set("string", "\"value\"");
	config.set("integer", 2);
	config.set("long", 123456789L);
	config.set("double", 3.1415926535);
	config.set("bool_array", Arrays.asList(true, false, true, false));
	config.set("config", subConfig);
	config.set("table_array", tableArray);
	config.set("enum", TestEnum.A);

	StringWriter stringWriter = new StringWriter();
	TomlWriter writer = new TomlWriter();
	writer.setIndentArrayElementsPredicate(array -> array.size() > 3);
	writer.setWriteTableInlinePredicate(table -> table.size() <= 2);
	writer.write(config, stringWriter);

	System.out.println("Written:");
	System.out.println(stringWriter);
}
 
Example #25
Source File: TomlWriterTest.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Test
public void noNulls() {
	Config config = TomlFormat.newConfig();
	Executable tryToWrite = () -> TomlFormat.instance().writer().writeToString(config);

	config.set("null", null);
	Assertions.assertThrows(WritingException.class, tryToWrite);

	config.set("null", NullObject.NULL_OBJECT);
	Assertions.assertThrows(WritingException.class, tryToWrite);
}
 
Example #26
Source File: JsonConfigTest.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Test
public void testReadEmptyObject() throws IOException {
	Config conf = new JsonParser().parse("{}");
	System.out.println(conf);
	assertTrue(conf.isEmpty());
	assertThrows(ParsingException.class, () -> {
		new JsonParser().parse("{\"this\":12, }");
	});
}
 
Example #27
Source File: ConfigSpecExample.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
public static void main(String[] args) {
	// Creates the ConfigSpec and defines how the config must be:
	ConfigSpec spec = new ConfigSpec();
	// defines an entry "key" of type String with a default value
	spec.define("key", "defaultValue");

	// defines an integer in range [-1;1], default 0
	spec.defineInRange("number", 0, -1, 1);

	// defines an entry "letter" that must be either 'a', 'b' or 'c'; default 'a'
	spec.defineInList("letter", 'a', Arrays.asList('a', 'b', 'c'));

	// You can also use defineOfClass with an enum:
	// This defines an entry "letter" that must be Letter.A, Letter.B or Letter.C, default A
	spec.defineOfClass("letter", Letter.A, Letter.class);
	// Redefining an entry overrides the previous definition.

	// Let's create a Config to use the ConfigSpec:
	Config config = Config.inMemory();
	config.set("key", "the value");// this is a valid entry of type String
	config.set("number", 1234);// number isn't in range [-1;1]
	config.set("unwanted_key", "abcdefg");// an entry that isn't in the specification
	// -- no "letter" entry

	// Checks if the config respects the configuration:
	boolean correct = spec.isCorrect(config);
	System.out.println("Correct: " + correct);

	// Corrects the configuration by using the default values where necessary:
	spec.correct(config);
	System.out.println("Config after correction: " + config);
	/*
	Explanation of the output:
	 - The "key" entry wasn't valid: the spec required it to be a String, it is the case.
	 - The "number" value wasn't in the specified range, therefore it has been replaced by the
	 default value 0.
	 - The "unwanted_key" entry wasn't in the spec, therefore it has been deleted.
	 - The "letter" entry was missing, therefore it has been added with the default value A.
	*/
}
 
Example #28
Source File: JsonConfigTest.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Test
public void testWriteThenRead() throws IOException {
	FancyJsonWriter writer = new FancyJsonWriter();
	writer.write(config, file, WritingMode.REPLACE);

	Config read = new JsonParser().parse(file, FileNotFoundAction.THROW_ERROR);
	assertEquals(TestEnum.A, read.getEnum("enum", TestEnum.class));

	System.out.println("config: " + config);
	System.out.println("read: " + read);

	assertEquals(read.toString(), config.toString());
}
 
Example #29
Source File: JsonParser.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
private void parseKeyValue(JsonTokenizer tokenizer, JsonToken keyToken, Config dst) {
	if (keyToken != VALUE_STRING)
		throw new ParsingException("");

	CharSequence key = tokenizer.textValue();
	JsonToken separator = tokenizer.next();
	if (separator != KV_SEPARATOR)
		throw new ParsingException("");

	Object value = parseValue(tokenizer, tokenizer.next());
	dst.set(single(key.toString()), value);
}
 
Example #30
Source File: JsonParser.java    From night-config with GNU Lesser General Public License v3.0 5 votes vote down vote up
private Config parseConfigContent(JsonTokenizer tokenizer, Config dst) {
	JsonToken token = tokenizer.next();
	if (token == OBJECT_END)
		return dst;
	parseKeyValue(tokenizer, token, dst);
	while ((token = tokenizer.next()) == ELEMENT_SEPARATOR) {
		parseKeyValue(tokenizer, tokenizer.next(), dst);
	}
	if (token != OBJECT_END)
		throw new ParsingException("");
	return dst;
}