Source code for syside.json

  1"""
  2Convenience module intending to match the standard library ``json`` module.
  3"""
  4
  5from typing import overload
  6from warnings import warn
  7from dataclasses import dataclass
  8
  9from .. import core as syside
 10
 11
[docs] 12@dataclass 13class SerializationError(Exception): 14 """ 15 Error serializing element to SysML v2 JSON. 16 """ 17 18 report: syside.SerdeReport[syside.Element]
19 20
[docs] 21@dataclass 22class DeserializationError(Exception): 23 """ 24 Error serializing element to SysML v2 JSON. 25 """ 26 27 model: syside.DeserializedModel 28 report: syside.SerdeReport[syside.Element | str | syside.DocumentSegment]
29 30
[docs] 31class SerdeWarning(Warning): 32 """ 33 Class for warnings from serialization and deserialization 34 """
35 36
[docs] 37def dumps( 38 element: syside.Element, 39 options: syside.SerializationOptions, 40 indent: int = 2, 41 use_spaces: bool = True, 42 final_new_line: bool = True, 43 include_cross_ref_uris: bool = True, 44) -> str: 45 """ 46 Serialize ``element`` to a SysML v2 JSON ``str``. 47 48 See the documentation of the :py:class:`SerializationOptions 49 <syside.SerializationOptions>` class for documentation of the possible 50 options. The options object constructed with 51 :py:meth:`SerializationOptions.minimal 52 <syside.SerializationOptions.minimal>` instructs to produce a minimal JSON 53 without any redundant elements that results in significantly smaller JSONs. 54 Examples of redundant information that is avoided using minimal 55 configuration are: 56 57 + including fields for null values; 58 + including fields whose values match the default values; 59 + including redefined fields that are duplicates of redefining fields; 60 + including derived fields that can be computed from minimal JSON (for 61 example, the result value of evaluating an expression); 62 + including implied relationships. 63 64 .. note:: 65 66 SysIDE does not construct all derived properties yet. Therefore, setting 67 ``options.include_derived`` to ``True`` may result in a JSON that does 68 not satisfy the schema. 69 70 :param element: 71 The SysML v2 element to be serialized to SysML v2 JSON. 72 :param options: 73 The serialization options to use when serializing SysML v2 to JSON. 74 :param indent: 75 How many space or tab characters to use for indenting the JSON. 76 :param use_spaces: 77 Whether use spaces or tabs for indentation. 78 :param final_new_line: 79 Whether to add a newline character at the end of the generated string. 80 :param include_cross_ref_uris: 81 Whether to add potentially relative URIs as ``@uri`` property to 82 references of Elements from documents other than the one owning 83 ``element``. Note that while such references are non-standard, they 84 match the behaviour of XMI exports in Pilot implementation which use 85 relative URIs for references instead of plain element IDs. 86 :return: 87 ``element`` serialized as JSON. 88 """ 89 90 writer = syside.JsonStringWriter( 91 indent=indent, 92 use_spaces=use_spaces, 93 final_new_line=final_new_line, 94 include_cross_ref_uris=include_cross_ref_uris, 95 ) 96 97 report = syside.serialize(element, writer, options) 98 99 if not report: 100 raise SerializationError(report) 101 102 for msg in report.messages: 103 if msg.severity == syside.DiagnosticSeverity.Warning: 104 warn(msg.message, category=SerdeWarning, stacklevel=2) 105 106 return writer.result
107 108 109@overload 110def loads( 111 s: str, 112 document: syside.Document, 113 attributes: syside.AttributeMap | None = None, 114) -> syside.DeserializedModel: 115 """ 116 Deserialize a model from ``s`` into an already existing ``document``. 117 118 :param s: 119 The string contained serialized SysML model in JSON array. 120 :param document: 121 The document the model will be deserialized into. 122 :param attributes: 123 Attribute mapping of ``s``. If none provided, this will attempt to infer 124 a corresponding mapping or raise a ``ValueError``. 125 :return: 126 Model deserialized from JSON array. Note that references into other 127 documents will not be resolved, users will need to resolve them by 128 calling ``link`` on the returned model. See also :py:class:`IdMap 129 <syside.IdMap>`. 130 """ 131 132 133@overload 134def loads( 135 s: str, 136 document: syside.Url | str, 137 attributes: syside.AttributeMap | None = None, 138) -> tuple[syside.DeserializedModel, syside.SharedMutex[syside.Document]]: 139 """ 140 Create a new ``document`` and deserialize a model from ``s`` into it. 141 142 :param s: 143 The string contained serialized SysML model in JSON array. 144 :param document: 145 A URI in the form of :py:class:`Url <syside.Url>` or a string, new 146 document will be created with. If URI path has no extension, or the 147 extension does not match ``sysml`` or ``kerml``, ``ValueError`` is 148 raised. 149 :param attributes: 150 Attribute mapping of ``s``. If none provided, this will attempt to infer 151 a corresponding mapping or raise a ``ValueError``. 152 :return: 153 Model deserialized from JSON array and the newly created document. Note that 154 references into other documents will not be resolved, users will need to 155 resolve them by calling ``link`` on the returned model. See also 156 :py:class:`IdMap <syside.IdMap>`. 157 """ 158 159
[docs] 160def loads( 161 s: str, 162 document: syside.Document | syside.Url | str, 163 attributes: syside.AttributeMap | None = None, 164) -> ( 165 syside.DeserializedModel 166 | tuple[syside.DeserializedModel, syside.SharedMutex[syside.Document]] 167): 168 """loads implementation""" 169 reader = syside.JsonReader() 170 171 new_doc: syside.SharedMutex[syside.Document] | None = None 172 if isinstance(document, str): 173 document = syside.Url(document) 174 if isinstance(document, syside.Url): 175 ext = document.path.rsplit(".", 1)[-1].lower() 176 if ext == "sysml": 177 lang = syside.ModelLanguage.SysML 178 elif ext == "kerml": 179 lang = syside.ModelLanguage.KerML 180 else: 181 raise ValueError(f"Unknown document language, could not infer from '{ext}'") 182 new_doc = syside.Document.create_st(url=document, language=lang) 183 with new_doc.lock() as doc: 184 document = doc # appease pylint 185 186 with reader.bind(s) as json: 187 if attributes is None: 188 attributes = json.attribute_hint() 189 if attributes is None: 190 raise ValueError("Cannot deserialize model with unmapped attributes") 191 192 model, report = syside.deserialize(document, json, attributes) 193 194 if not report: 195 raise DeserializationError(model, report) 196 197 for msg in report.messages: 198 if msg.severity == syside.DiagnosticSeverity.Warning: 199 warn(msg.message, category=SerdeWarning, stacklevel=2) 200 201 if new_doc: 202 return model, new_doc 203 return model