// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. import 'dart:convert' show jsonDecode; Map decodeJsonMap(String json) { final root = jsonDecode(json); if (root case Map v) return v; throw const FormatException('root must be a map'); } extension ExpectJson on Map { bool expectBool(String key) { if (this[key] case bool v) return v; throw FormatException('The value at "$key" must be a bool:\n$toString()'); } num expectNumber(String key) { if (this[key] case num v) return v; throw FormatException('The value at "$key" must be a number:\n$toString()'); } String expectString(String key) { if (this[key] case String v) return v; throw FormatException('The value at "$key" must be a string:\n$toString()'); } Uri expectUri(String key) { try { return Uri.parse(expectString(key)); } on FormatException { throw FormatException('The value at "$key" must be a URI:\n$toString()'); } } Map expectMap(String key) { if (this[key] case Map v) return v; throw FormatException('The value at "$key" must be a map:\n$toString()'); } Map? optionalMap(String key) { if (containsKey(key)) { return expectMap(key); } return null; } Uri? optionalUri(String key) { if (containsKey(key)) { return expectUri(key); } return null; } List expectList(String key) { if (this[key] case List v) return v; throw FormatException('The value at "$key" must be a list:\n$toString()'); } Iterable> expectListObjects(String key) sync* { final list = expectList(key); for (final entry in list) { if (entry case Map v) { yield v; } else { throw FormatException( 'The value at "$key" must be a list of map:\n$toString()', ); } } } }