ElementType.fromJson constructor
ElementType.fromJson(
- Map<String, dynamic> json
)
Implementation
factory ElementType.fromJson(Map<String, dynamic> json) {
// Based on original code, it seems `description` and `properties` are at top level:
// {
// "type": "object",
// "description": "...",
// "required": [...],
// "properties": {
// "tagName": {
// "type": "object",
// "required": [...],
// "properties": { ... }
// }
// }
// }
final description = json["description"] as String?;
final propertiesMap = json["properties"] as Map;
// The Python code picks up the first key in properties as the tagName and uses its properties
// structure:
// "properties": {
// "tagName": {
// "type": "object",
// ...
// "properties": {
// "prop_name": { "description":..., "type": ... or "array" ... }
// }
// }
// }
if (propertiesMap.isEmpty) {
throw MeshSchemaValidationException("Invalid schema json: no properties found");
}
// In Python code, it uses `for k, type_json in json["properties"].items()` then returns inside.
// So effectively, we take the first entry as the element definition.
final firstEntry = propertiesMap.entries.first;
final tagName = firstEntry.key;
final typeJson = firstEntry.value as Map;
final propMap = typeJson["properties"] as Map;
final properties = <ElementProperty>[];
propMap.forEach((propName, p) {
final pMap = p as Map;
final propDescription = pMap["description"] as String?;
final pType = pMap["type"];
if (pType == "array") {
if (pMap["items"] != null && pMap["items"] is Map && pMap["items"]["anyOf"] != null) {
// handle ChildProperty
final items = pMap["items"] as Map;
final anyOf = items["anyOf"] as List<dynamic>;
final childTagNames = <String>[];
for (var refObj in anyOf) {
final refMap = refObj as Map;
final refStr = refMap["\$ref"] as String;
const prefix = "#/\$defs/";
final childTagName = refStr.startsWith(prefix) ? refStr.substring(prefix.length) : refStr;
childTagNames.add(childTagName);
}
properties.add(ChildProperty(name: propName, description: propDescription, childTagNames: childTagNames));
} else if (pMap["prefixItems"] != null) {
final anyOf = pMap["prefixItems"] as List<dynamic>;
final childTagNames = <String>[];
for (var refObj in anyOf) {
final refMap = refObj as Map;
final refStr = refMap["\$ref"] as String;
const prefix = "#/\$defs/";
final childTagName = refStr.startsWith(prefix) ? refStr.substring(prefix.length) : refStr;
childTagNames.add(childTagName);
}
properties.add(ChildProperty(name: propName, description: propDescription, childTagNames: childTagNames, ordered: true));
} else {
throw MeshSchemaValidationException("Invalid array type encountered");
}
} else {
// handle ValueProperty
// pType should be a string matching SimpleValue
final valTypeStr = pType as String;
final valType = SimpleValue.fromString(valTypeStr);
if (valType == null) {
throw MeshSchemaValidationException("Invalid value type: $valTypeStr");
}
final enumValue = pMap["enum"] as List<dynamic>?;
properties.add(ValueProperty(name: propName, description: propDescription, type: valType, enumValues: enumValue));
}
});
return ElementType(tagName: tagName, description: description, properties: properties);
}