Here’s the code:
import syside
from pathlib import Path
from datetime import datetime, timezone
import json
from pprint import pprint
from typing import List, Dict, Any
import pathlib
import os
import warnings
def _create_json_writer() -> syside.JsonStringWriter:
json_options = syside.JsonStringOptions()
json_options.include_cross_ref_uris = False
json_options.indent = False
writer = syside.JsonStringWriter(json_options)
return writer
def _create_serialization_options() -> syside.SerializationOptions:
options = syside.SerializationOptions().minimal().with_options(
use_standard_names=True,
include_derived=True,
include_redefined=True,
include_default=False,
include_optional=False,
include_implied=True,
)
options.fail_action = syside.FailAction.Ignore
return options
def _model_to_json (model:syside.Model, minimal:bool=False):
# Export the model to JSON
assert len(model.user_docs) == 1
writer = _create_json_writer()
if minimal:
options = syside.SerializationOptions.minimal()
else:
options =_create_serialization_options()
with model.user_docs[0].lock() as locked:
syside.serialize(locked.root_node, writer, options)
json_string = writer.result
now_str = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
obj = json.loads(json_string)
for element in obj:
if element.get("@type") == "Namespace" and "owningRelationship" not in element:
element["qualifiedName"] = now_str # set the value here
#print(element)
break
return json.dumps(obj, indent=2)
def convert_sysml_file_textual_to_json2(sysml_file_path:str, json_out_path:str = None, minimal:bool=False) -> str:
# load sysml textual notation and create json dump
model, diagnostics = syside.try_load_model([sysml_file_path])
# Only errors cause an exception. SysIDE may also report warnings and
# informational messages
assert not diagnostics.contains_errors(warnings_as_errors=True)
json_string = _model_to_json(model, minimal)
if json_out_path is not None:
with open(json_out_path, "w", encoding="utf-8") as f:
f.write(json_string)
data = json.loads(json_string)
return json_string
def convert_json_to_sysml_textual2(json_flexo:str, debug:bool=False):
captured_warnings = []
with warnings.catch_warnings(record=True) as wlist:
warnings.simplefilter("always") # capture all warnings
# Normalize input to a JSON string (no double-encoding!)
if isinstance(json_flexo, (dict, list)):
json_in = json.dumps(json_flexo, ensure_ascii=False)
elif isinstance(json_flexo, str):
json_in = json_flexo
else:
raise TypeError(f"json_flexo must be dict/list/str, got {type(json_flexo).__name__}")
# 1) Clean dangling refs & incomplete relationships → JSON string out
#json_clean = clean_sysml_json_for_syside(json_in, preserve_refs_with_uri=True, debug=debug)
# 3) Deserialize
try:
deserialized_model, _ = syside.json.loads(json_in, "memory:///import.sysml")
except Exception as exc:
# Try to catch the specific syside error type first
try:
from syside.json import DeserializationError # sometimes exported here
except Exception:
try:
from syside.core import DeserializationError # or here, depending on version
except Exception:
DeserializationError = type(None) # fallback so isinstance won't match
if isinstance(exc, DeserializationError):
# Many versions set these as attributes...
report = getattr(exc, "report", None)
model = getattr(exc, "model", None)
# ...but they are always present in .args as a fallback
if report is None and getattr(exc, "args", None):
if len(exc.args) >= 2:
model = exc.args[0]
report = exc.args[1]
captured_warnings.append(f"Deserialization failed: {report}")
return None, captured_warnings
else:
# Not a syside deserialization error; re-raise (or handle differently)
raise
# Collect warnings from this phase
for w in wlist:
captured_warnings.append(str(w.message))
# Create an IdMap that will be used to link deserialized models together
map = syside.IdMap()
# Create an environment to have access to stdlib docs
# If you have exported the stdlib to JSON as well, you do not need this
# environment. However, currently we have a bug that prevents us from
# loading the stdlib from JSON.
for mutex in syside.Environment.get_default().documents:
with mutex.lock() as dep:
map.insert_or_assign(dep)
try:
report, success = deserialized_model.link(map)
except Exception as exc:
try:
from syside.core import DeserializationError # or here, depending on version
except Exception:
DeserializationError = type(None) # fallback so isinstance won't match
if isinstance(exc, DeserializationError):
# Many versions set these as attributes...
report = getattr(exc, "report", None)
model = getattr(exc, "model", None)
# ...but they are always present in .args as a fallback
if report is None and getattr(exc, "args", None):
if len(exc.args) >= 2:
model = exc.args[0]
report = exc.args[1]
print("Deserialization failed. Diagnostic report:")
else:
# Not a syside deserialization error; re-raise (or handle differently)
raise
# Save the deserialized model to a file
root_namespace = deserialized_model.document.root_node
printer_cfg = syside.PrinterConfig(line_width=80, tab_width=2)
printer = syside.ModelPrinter.sysml()
sysml_text = syside.pprint(root_namespace, printer, printer_cfg)
return (sysml_text, deserialized_model), captured_warnings
import json, pprint
EXAMPLE_DIR = pathlib.Path(os.getcwd())
MODEL_FILE_PATH = EXAMPLE_DIR / 't-v4.sysml'
# use minimal = True to get the compact version
raw_jsonf = convert_sysml_file_textual_to_json2(sysml_file_path=MODEL_FILE_PATH, minimal=False)
data = json.loads(raw_jsonf) # parse JSON string into Python objects
(sysml_text, model), warnings = convert_json_to_sysml_textual2(data)
print(f"Created SysML model:\n{sysml_text}")