diff --git a/include/libcamera/internal/yaml_parser.h b/include/libcamera/internal/yaml_parser.h
index 064cf44381d7..eb39ea8c79e4 100644
--- a/include/libcamera/internal/yaml_parser.h
+++ b/include/libcamera/internal/yaml_parser.h
@@ -24,12 +24,21 @@ class YamlParserContext;
 class YamlObject
 {
 private:
-	using DictContainer = std::map<std::string, std::unique_ptr<YamlObject>>;
+	struct Value {
+		Value(std::string &&k, std::unique_ptr<YamlObject> &&v)
+			: key(std::move(k)), value(std::move(v))
+		{
+		}
+		std::string key;
+		std::unique_ptr<YamlObject> value;
+	};
+
+	using Container = std::vector<Value>;
 	using ListContainer = std::vector<std::unique_ptr<YamlObject>>;
 
 public:
 #ifndef __DOXYGEN__
-	template<typename Container, typename Derived>
+	template<typename Derived>
 	class Iterator
 	{
 	public:
@@ -65,10 +74,10 @@ public:
 		}
 
 	protected:
-		typename Container::const_iterator it_;
+		Container::const_iterator it_;
 	};
 
-	template<typename Container, typename Iterator>
+	template<typename Iterator>
 	class Adapter
 	{
 	public:
@@ -91,7 +100,7 @@ public:
 		const Container &container_;
 	};
 
-	class ListIterator : public Iterator<ListContainer, ListIterator>
+	class ListIterator : public Iterator<ListIterator>
 	{
 	public:
 		using value_type = const YamlObject &;
@@ -100,16 +109,16 @@ public:
 
 		value_type operator*() const
 		{
-			return *it_->get();
+			return *it_->value.get();
 		}
 
 		pointer operator->() const
 		{
-			return it_->get();
+			return it_->value.get();
 		}
 	};
 
-	class DictIterator : public Iterator<DictContainer, DictIterator>
+	class DictIterator : public Iterator<DictIterator>
 	{
 	public:
 		using value_type = std::pair<const std::string &, const YamlObject &>;
@@ -118,17 +127,17 @@ public:
 
 		value_type operator*() const
 		{
-			return { it_->first, *it_->second.get() };
+			return { it_->key, *it_->value.get() };
 		}
 	};
 
-	class DictAdapter : public Adapter<DictContainer, DictIterator>
+	class DictAdapter : public Adapter<DictIterator>
 	{
 	public:
 		using key_type = std::string;
 	};
 
-	class ListAdapter : public Adapter<ListContainer, ListIterator>
+	class ListAdapter : public Adapter<ListIterator>
 	{
 	};
 #endif /* __DOXYGEN__ */
@@ -167,7 +176,7 @@ public:
 #endif
 	T get(const T &defaultValue, bool *ok = nullptr) const;
 
-	DictAdapter asDict() const { return DictAdapter{ dictionary_ }; }
+	DictAdapter asDict() const { return DictAdapter{ list_ }; }
 	ListAdapter asList() const { return ListAdapter{ list_ }; }
 
 	const YamlObject &operator[](std::size_t index) const;
@@ -189,8 +198,8 @@ private:
 	Type type_;
 
 	std::string value_;
-	ListContainer list_;
-	DictContainer dictionary_;
+	Container list_;
+	std::map<std::string, YamlObject *> dictionary_;
 };
 
 class YamlParser final
diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/yaml_parser.cpp
index 5c45e44e49c3..e30de050a0ea 100644
--- a/src/libcamera/yaml_parser.cpp
+++ b/src/libcamera/yaml_parser.cpp
@@ -91,7 +91,6 @@ std::size_t YamlObject::size() const
 {
 	switch (type_) {
 	case Type::Dictionary:
-		return dictionary_.size();
 	case Type::List:
 		return list_.size();
 	default:
@@ -311,11 +310,11 @@ Size YamlObject::get(const Size &defaultValue, bool *ok) const
 	 * that ok == nullptr.
 	 */
 	bool valid;
-	uint32_t width = list_[0]->get<uint32_t>(0, &valid);
+	uint32_t width = list_[0].value->get<uint32_t>(0, &valid);
 	if (!valid)
 		return defaultValue;
 
-	uint32_t height = list_[1]->get<uint32_t>(0, &valid);
+	uint32_t height = list_[1].value->get<uint32_t>(0, &valid);
 	if (!valid)
 		return defaultValue;
 
@@ -379,7 +378,7 @@ const YamlObject &YamlObject::operator[](std::size_t index) const
 	if (type_ != Type::List || index >= size())
 		return empty;
 
-	return *list_[index];
+	return *list_[index].value;
 }
 
 /**
@@ -395,7 +394,7 @@ const YamlObject &YamlObject::operator[](std::size_t index) const
  */
 bool YamlObject::contains(const std::string &key) const
 {
-	if (dictionary_.find(key) == dictionary_.end())
+	if (dictionary_.find(std::ref(key)) == dictionary_.end())
 		return false;
 
 	return true;
@@ -667,16 +666,16 @@ int YamlParserContext::parseNextYamlObject(YamlObject &yamlObject, EventPtr even
 		yamlObject.type_ = YamlObject::Type::List;
 		auto &list = yamlObject.list_;
 		auto handler = [this, &list](EventPtr evt) {
-			list.emplace_back(new YamlObject());
-			return parseNextYamlObject(*list.back(), std::move(evt));
+			list.emplace_back(std::string{}, std::make_unique<YamlObject>());
+			return parseNextYamlObject(*list.back().value, std::move(evt));
 		};
 		return parseDictionaryOrList(YamlObject::Type::List, handler);
 	}
 
 	case YAML_MAPPING_START_EVENT: {
 		yamlObject.type_ = YamlObject::Type::Dictionary;
-		auto &dictionary = yamlObject.dictionary_;
-		auto handler = [this, &dictionary](EventPtr evtKey) {
+		auto &list = yamlObject.list_;
+		auto handler = [this, &list](EventPtr evtKey) {
 			/* Parse key */
 			if (evtKey->type != YAML_SCALAR_EVENT) {
 				LOG(YamlParser, Error) << "Expect key at line: "
@@ -694,10 +693,19 @@ int YamlParserContext::parseNextYamlObject(YamlObject &yamlObject, EventPtr even
 			if (!evtValue)
 				return -EINVAL;
 
-			auto elem = dictionary.emplace(key, std::make_unique<YamlObject>());
-			return parseNextYamlObject(*elem.first->second.get(), std::move(evtValue));
+			auto &elem = list.emplace_back(std::move(key),
+						       std::make_unique<YamlObject>());
+			return parseNextYamlObject(*elem.value, std::move(evtValue));
 		};
-		return parseDictionaryOrList(YamlObject::Type::Dictionary, handler);
+		int ret = parseDictionaryOrList(YamlObject::Type::Dictionary, handler);
+		if (ret)
+			return ret;
+
+		auto &dictionary = yamlObject.dictionary_;
+		for (const auto &elem : list)
+			dictionary.emplace(elem.key, elem.value.get());
+
+		return 0;
 	}
 
 	default:
@@ -753,6 +761,9 @@ int YamlParserContext::parseNextYamlObject(YamlObject &yamlObject, EventPtr even
  * The YamlParser::parse() function takes an open FILE, parses its contents, and
  * returns a pointer to a YamlObject corresponding to the root node of the YAML
  * document.
+ *
+ * The parser preserves the order of items in the YAML file, for both lists and
+ * dictionaries.
  */
 
 /**
