Metamodel classes and JSON¶
opensysml.metamodel holds one generated class per SysML/KerML metaclass
(Element, Namespace, Feature, PartUsage, ...), each with one read-only
property per metamodel property. opensysml.read_json builds those objects
from a JSON export in pure Python: it needs no sysml-grpc service, never
converts to notation and never writes back.
This is not the same as typed classes:
opensysml.generate writes classes for the definitions in your model
(Vehicle, Engine) over service-backed instances, while the metamodel
classes describe the language's own elements and are the same for every model.
import opensysml
from opensysml.metamodel import Feature, PartUsage
g = opensysml.read_json("vehicle.full.json") # sysml-toolkit full-json
for p in g.all(PartUsage):
print(p.qualifiedName, [t.name for t in p.type], len(p.ownedFeature))
assert isinstance(p, Feature) # follows the spec hierarchy
The classes follow the metamodel's inheritance, so graph.all(Feature) also
returns every PartUsage. graph[id] looks an element up by @id, and
graph.roots() returns the namespaces the document records no owner for. References are
resolved when read, and many-valued properties return tuples.
Names¶
Each property's primary name is snake_case (owned_feature, is_abstract);
the spec's camelCase name (ownedFeature, isAbstract) is an alias for the
same descriptor, so both spellings behave identically and type-check. A name
that would be a Python keyword gets a trailing _. PartUsage.from_json_key("partDefinition")
and PartUsage.json_key("part_definition") convert between the two. The
package ships py.typed, so mypy and pyright see every property's type.
Inputs¶
read_json accepts a file path (a str is always a path, never JSON text),
bytes, a single element object, or a list of element objects, with @id,
@type and {"@id": ...} references. It also unwraps SysML v2 API DataVersion
(identity/payload) and Commit (change) envelopes and sysml:-prefixed or
IRI types. An @type the metamodel does not know is read as its nearest known
ancestor when you pass supertypes={"MyType": "PartUsage", ...}, otherwise as
Element; element.json_type keeps the written name.
Missing, empty and dangling values¶
A property the JSON does not carry raises NotSupplied (its .derived says
whether the property is computed). It never reads as None or () instead:
only an explicit null or [] in the JSON means empty. A reference to an @id
the document does not contain raises UnresolvedReference when read. A reference
to an element of the wrong metaclass raises MalformedValue. Some exports write
derived values outside their range (sysml-toolkit full-json sets a requirement
definition's result to the definition itself, for example);
read_json(..., check_ranges=False) returns such elements as written instead.
OpenSysML's api-json export carries the owned properties it writes plus some derived ones
(ownedFeature, owner, qualifiedName, ownedMember, ...). It carries no feature,
inheritedFeature or definition, and type only on some usages, so those reads raise
NotSupplied with derived=True until the engine serves derived properties. The export also
writes no null and no []: an unset owned property, such as an unnamed element's
declaredName, is absent and raises NotSupplied too. sysml-toolkit full-json carries derived
properties as well. A reference to an element the document does not include, such as a
standard-library element, raises UnresolvedReference when read.
Providing engine-computed derived properties, implementing metamodel operations, and loading JSON
into the OpenSysML engine are separate follow-up work.
See the Python API reference for the full error table.