NTV.json_ntv.ntv_connector

Created on Feb 27 2023

@author: Philippe@loco-labs.io

The NTV.ntv_connector module is part of the NTV.json_ntv package (specification document).

A NtvConnector is defined by:

  • clas_obj: str - define the class name of the object to convert
  • clas_typ: str - define the NTVtype of the converted object
  • to_obj_ntv: method - converter from JsonNTV to the object
  • to_json_ntv: method - converter from the object to JsonNTV

It contains :

  1# -*- coding: utf-8 -*-
  2"""
  3Created on Feb 27 2023
  4
  5@author: Philippe@loco-labs.io
  6
  7The `NTV.ntv_connector` module is part of the `NTV.json_ntv` package ([specification document](
  8https://github.com/loco-philippe/NTV/blob/main/documentation/JSON-NTV-standard.pdf)).
  9
 10A NtvConnector is defined by:
 11- clas_obj: str - define the class name of the object to convert
 12- clas_typ: str - define the NTVtype of the converted object
 13- to_obj_ntv: method - converter from JsonNTV to the object
 14- to_json_ntv: method - converter from the object to JsonNTV
 15    
 16It contains :
 17
 18- methods `from_csv` and `to_csv` to convert CSV files and 'tab' NTV entity
 19- the child classes of `NTV.json_ntv.ntv.NtvConnector` abstract class:
 20    - `SfieldConnec`:    'field' connector
 21    - `SdatasetConnec`:  'tab' connector
 22    - `NfieldConnec`:    'field' connector
 23    - `NdatasetConnec`:  'tab' connector
 24    - `MermaidConnec`:   '$mermaid' connector
 25    - `ShapelyConnec`:   'geometry' connector
 26    - `CborConnec`:      '$cbor' connector
 27
 28
 29"""
 30import datetime
 31import csv
 32import json
 33import pandas as pd
 34import numpy as np
 35
 36from json_ntv.ntv import Ntv, NtvConnector, NtvList, NtvSingle, NtvTree
 37#from observation import Sfield
 38
 39
 40def from_csv(file_name, single_tab=True, dialect='excel', **fmtparams):
 41    ''' return a 'tab' NtvSingle from a csv file
 42
 43    *parameters*
 44
 45    - **file_name** : name of the csv file
 46    - **single_tab** : boolean (default True) - if True return a 'tab' NtvSingle,
 47    else return a NtvSet.
 48    - **dialect, fmtparams** : parameters of csv.DictReader object'''
 49    with open(file_name, newline='') as csvfile:
 50        reader = csv.DictReader(csvfile, dialect=dialect, **fmtparams)
 51        names = reader.fieldnames
 52        list_ntv_value = [[] for nam in names]
 53        for row in reader:
 54            for ind_field, val in enumerate(list(row.values())):
 55                list_ntv_value[ind_field].append(json.loads(val))
 56    list_ntv = []
 57    for ind_field, field in enumerate(names):
 58        list_ntv.append(
 59            NtvList(list_ntv_value[ind_field], *Ntv.from_obj_name(field)[:2]))
 60    if single_tab:
 61        return NtvSingle(NtvList(list_ntv, None, None).to_obj(), None, 'tab')
 62    return NtvList(list_ntv, None, None)
 63
 64
 65def to_csv(file_name, ntv, *args, restval='', extrasaction='raise', dialect='excel', **kwds):
 66    ''' convert a 'tab' NtvSingle into csv file and return the file name
 67
 68    *parameters*
 69
 70    - **file_name** : name of the csv file
 71    - **ntv** : 'tab' NtvSingle to convert
 72    - **args, restval, extrasaction, dialect, kwds** : parameters of csv.DictWriter object'''
 73    if isinstance(ntv, NtvSingle):
 74        ntv_set = Ntv.obj(ntv.ntv_value)
 75    else:
 76        ntv_set = ntv
 77    list_ntv = [Ntv.obj(field) for field in ntv_set]
 78    fieldnames = [ntv_field.json_name(string=True) for ntv_field in list_ntv]
 79    with open(file_name, 'w', newline='') as csvfile:
 80        writer = csv.DictWriter(csvfile, fieldnames=fieldnames, restval=restval,
 81                                extrasaction=extrasaction, dialect=dialect, *args, **kwds)
 82        writer.writeheader()
 83        for i in range(len(list_ntv[0])):
 84            writer.writerow({name: field_ntv[i].to_obj(field_ntv.ntv_type, encoded=True)
 85                             for name, field_ntv in zip(fieldnames, list_ntv)})
 86    return file_name
 87
 88
 89class ShapelyConnec(NtvConnector):
 90    '''NTV connector for geographic location'''
 91
 92    clas_obj = 'geometry'
 93    clas_typ = 'geometry'
 94
 95    @staticmethod
 96    def to_obj_ntv(ntv_value, **kwargs):
 97        ''' convert ntv_value into a shapely geometry object defined by 'type_geo'.
 98
 99        *Parameters*
100
101        - **type_geo** : type of geometry (point, multipoint, line, multiline',
102        polygon, multipolygon)
103        - **ntv_value** : array - coordinates'''
104        from shapely import geometry
105        type_geo = ShapelyConnec.type_geo(ntv_value) if not 'type_geo' in kwargs \
106            or kwargs['type_geo'] == 'geometry' else kwargs['type_geo']
107        return geometry.shape({"type": type_geo, "coordinates": ntv_value})
108
109    @staticmethod
110    def to_json_ntv(value, name=None, typ=None):
111        ''' convert NTV object (value, name, type) into NTV json (json-value, name, type).
112
113        *Parameters*
114
115        - **typ** : string (default None) - NTV type of geometry (point, multipoint,
116        line, multiline', polygon, multipolygon),
117        - **name** : string (default None) - name of the NTV object
118        - **value** : shapely geometry'''
119        return (Ntv._listed(value.__geo_interface__['coordinates']), name, typ)
120
121    @staticmethod
122    def to_coord(geom):
123        ''' convert shapely geometry into geojson coordinates.'''
124        return Ntv._listed(geom.__geo_interface__['coordinates'])
125
126    @staticmethod
127    def to_geojson(geom):
128        ''' convert shapely geometry into geojson string'''
129        return json.dumps(geom.__geo_interface__)
130
131    @staticmethod
132    def from_geojson(geojson):
133        ''' convert geojson string into shapely geometry.'''
134        from shapely import geometry
135        return geometry.shape(json.loads(geojson))
136    
137    @staticmethod 
138    def to_geometry(value):
139        '''convert geojson coordinates into shapely geometry'''
140        return ShapelyConnec.to_obj_ntv(value, type_geo=ShapelyConnec.type_geo(value))
141    
142    @staticmethod 
143    def type_geo(value):
144        '''return geometry type of the value'''
145        if not value or not isinstance(value, list):
146            return 'not a geometry'
147        val = value[0]
148        if not isinstance(val, list):
149            return 'point'
150        val = val[0]
151        if not isinstance(val, list):
152            return 'line'        
153        return 'polygon'
154    
155class CborConnec(NtvConnector):
156    '''NTV connector for binary data'''
157
158    clas_obj = 'bytes'
159    clas_typ = '$cbor'
160
161    @staticmethod
162    def to_obj_ntv(ntv_value, **kwargs):
163        ''' convert json ntv_value into a binary CBOR object (no parameters).'''
164        import cbor2
165        return cbor2.dumps(ntv_value, datetime_as_timestamp=True,
166                           timezone=datetime.timezone.utc, canonical=False,
167                           date_as_datetime=True)
168
169    @staticmethod
170    def to_json_ntv(value, name=None, typ=None):
171        ''' convert NTV binary object (value, name, type) into NTV json (json-value, name, type).
172
173        *Parameters*
174
175        - **typ** : string (default None) - type of the NTV object,
176        - **name** : string (default None) - name of the NTV object
177        - **value** : binary data'''
178        import cbor2
179        return (cbor2.loads(value), name, typ)
180
181
182class NfieldConnec(NtvConnector):
183    '''NTV connector for NTV Field data'''
184
185    clas_obj = 'Nfield'
186    clas_typ = 'field'
187
188    @staticmethod
189    def to_obj_ntv(ntv_value, **kwargs):
190        ''' convert json ntv_value into a NTV Field object (no parameters).'''
191        from observation.fields import Nfield
192        ntv = Ntv.obj(ntv_value)
193        return Nfield.from_ntv(ntv)
194
195    @staticmethod
196    def to_json_ntv(value, name=None, typ=None):
197        ''' convert NTV Field object (value, name, type) into NTV json (json-value, name, type).
198
199        *Parameters*
200
201        - **typ** : string (default None) - type of the NTV object,
202        - **name** : string (default None) - name of the NTV object
203        - **value** : NTV Field values (default format)'''
204        return (value.to_ntv(name=True).to_obj(), name,
205                NfieldConnec.clas_typ if not typ else typ)
206
207
208class SfieldConnec(NtvConnector):
209    '''NTV connector for simple Field data'''
210
211    clas_obj = 'Sfield'
212    clas_typ = 'field'
213
214    @staticmethod
215    def to_obj_ntv(ntv_value, **kwargs):
216        ''' convert json ntv_value into a simple Field object (no parameters).'''
217        from observation.fields import Sfield
218        ntv = Ntv.obj(ntv_value)
219        return Sfield.from_ntv(ntv)
220
221    @staticmethod
222    def to_json_ntv(value, name=None, typ=None):
223        ''' convert simple Field object (value, name, type) into NTV json (json-value, name, type).
224
225        *Parameters*
226
227        - **typ** : string (default None) - type of the NTV object,
228        - **name** : string (default None) - name of the NTV object
229        - **value** : simple Field values (default format)'''
230        return (value.to_ntv(name=True).to_obj(), name,
231                NfieldConnec.clas_typ if not typ else typ)
232
233
234class NdatasetConnec(NtvConnector):
235    '''NTV connector for NTV Dataset data'''
236
237    clas_obj = 'Ndataset'
238    clas_typ = 'tab'
239
240    @staticmethod
241    def to_obj_ntv(ntv_value, **kwargs):
242        ''' convert json ntv_value into a NTV Dataset object (no parameters).'''
243        from observation.datasets import Ndataset
244
245        ntv = Ntv.obj(ntv_value)
246        return Ndataset.from_ntv(ntv)
247
248    @staticmethod
249    def to_json_ntv(value, name=None, typ=None):
250        ''' convert NTV Dataset object (value, name, type) into NTV json (json-value, name, type).
251
252        *Parameters*
253
254        - **typ** : string (default None) - type of the NTV object,
255        - **name** : string (default None) - name of the NTV object
256        - **value** : NTV Dataset values'''
257        return (value.to_ntv().to_obj(), name,
258                NdatasetConnec.clas_typ if not typ else typ)
259
260
261class SdatasetConnec(NtvConnector):
262    '''NTV connector for simple Dataset data'''
263
264    clas_obj = 'Sdataset'
265    clas_typ = 'tab'
266
267    @staticmethod
268    def to_obj_ntv(ntv_value, **kwargs):
269        ''' convert json ntv_value into a simple Dataset object (no parameters).'''
270        from observation.datasets import Sdataset
271
272        ntv = Ntv.obj(ntv_value)
273        return Sdataset.from_ntv(ntv)
274
275    @staticmethod
276    def to_json_ntv(value, name=None, typ=None):
277        ''' convert simple Dataset object (value, name, type) into NTV json
278        (json-value, name, type).
279
280        *Parameters*
281
282        - **typ** : string (default None) - type of the NTV object,
283        - **name** : string (default None) - name of the NTV object
284        - **value** : simple Dataset values'''
285        return (value.to_ntv().to_obj(), name,
286                SdatasetConnec.clas_typ if not typ else typ)
287
288class MermaidConnec(NtvConnector):
289    '''NTV connector for Mermaid diagram'''
290
291    clas_obj = 'Mermaid'
292    clas_typ = '$mermaid'
293
294    @staticmethod
295    def to_obj_ntv(ntv_value, **kwargs):
296        ''' convert ntv_value into a mermaid flowchart
297
298        *Parameters*
299
300        - **title**: String (default '') - title of the flowchart
301        - **disp**: Boolean (default False) - if true, return a display else return
302        a mermaid text diagram
303        - **row**: Boolean (default False) - if True, add the node row
304        - **leaves**: Boolean (default False) - if True, add the leaf row
305        '''
306        from base64 import b64encode
307        from IPython.display import Image, display
308
309        option = {'title': '', 'disp': False, 'row': False,
310                  'leaves': False} | kwargs
311        diagram = MermaidConnec.diagram
312        link = MermaidConnec._mermaid_link
313        ntv = Ntv.obj(ntv_value)
314        node_link = {'nodes': [], 'links': []}
315        dic_node = {}
316        if option['leaves']:
317            nodes = [node for node in NtvTree(
318                ntv) if not isinstance(node.val, list)]
319            dic_node = {node: row for row, node in enumerate(nodes)}
320        link(ntv, None, node_link, option['row'], dic_node, None)
321        mermaid_json = {option['title'] + ':$flowchart': {
322            'orientation': 'top-down',
323            'node::': {node[0]: node[1] for node in node_link['nodes']},
324            'link::': node_link['links']}}
325        if option['disp']:
326            return display(Image(url="https://mermaid.ink/img/" +
327                                 b64encode(diagram(mermaid_json).encode("ascii")).decode("ascii")))
328        return diagram(mermaid_json)
329
330    @staticmethod
331    def diagram(json_diag):
332        '''create a mermaid code from a mermaid json'''
333        ntv = Ntv.obj(json_diag)
334        erdiagram = MermaidConnec._er_diagram
335        flowchart = MermaidConnec._flowchart
336        diag_type = ntv.type_str[1:]
337        diag_txt = '---\ntitle: ' + ntv.name + '\n---\n' if ntv.name else ''
338        diag_txt += diag_type
339        match diag_type:
340            case 'erDiagram':
341                diag_txt += erdiagram(ntv)
342            case 'flowchart':
343                diag_txt += flowchart(ntv)
344        return diag_txt
345
346    @staticmethod
347    def _mermaid_node(ntv, def_typ_str, num, dic_node, ind):
348        '''create and return a node'''
349        j_name, j_sep, j_type = ntv.json_name(def_typ_str)
350        name = ''
351        if j_name:
352            name += '<b>' + j_name + '</b>\n'
353        if j_type:
354            name += j_type + '\n'
355        if ntv in dic_node:
356            num += ' ' + str(dic_node[ntv])
357        if num:
358            name += '<i>' + num + '</i>\n'
359        elif isinstance(ntv, NtvSingle):
360            if isinstance(ntv.val, str):
361                name += '<i>' + ntv.val + '</i>\n'
362            else:
363                name += '<i>' + json.dumps(ntv.val) + '</i>\n'
364            return [ntv.pointer(index=True, item_idx=ind).json(default='/'), 
365                    ['rectangle', name[:-1]]]
366        if not name:
367            name = '<b>::</b>\n'
368        name = name.replace('"', "'")
369        return [ntv.pointer(index=True, item_idx=ind).json(default='/'), 
370                ['roundedge', name[:-1]]]
371
372    @staticmethod
373    def _mermaid_link(ntv, def_typ_str, node_link, row, dic_node, ind):
374        '''add nodes and links from ntv in node_link '''
375        num = str(len(node_link['nodes'])) if row else ''
376        node_link['nodes'].append(MermaidConnec._mermaid_node(
377            ntv, def_typ_str, num, dic_node, ind))
378        if isinstance(ntv, NtvList):
379            for ind, ntv_val in enumerate(ntv):
380                MermaidConnec._mermaid_link(ntv_val, ntv.type_str,
381                                            node_link, row, dic_node, ind)
382                node_link['links'].append(
383                    [ntv.pointer(index=True).json(default='/'), 'normalarrow',
384                     ntv_val.pointer(index=True, item_idx=ind).json(default='/')])
385
386    @staticmethod
387    def _flowchart(ntv):
388        orientation = {'top-down': 'TD', 'top-bottom': 'TB',
389                       'bottom-top': 'BT', 'right-left': 'RL', 'left-right': 'LR'}
390        fcnode = MermaidConnec._fc_node
391        fclink = MermaidConnec._fc_link
392        flc = Ntv.obj(ntv.val)
393        diag_txt = ' ' + orientation[flc['orientation'].val]
394        for node in flc['node']:
395            diag_txt += fcnode(node)
396        for link in flc['link']:
397            diag_txt += fclink(link)
398        return diag_txt + '\n'
399
400    @staticmethod
401    def _fc_link(link):
402        link_t = {'normal': ' ---', 'normalarrow': ' -->',
403                  'dotted': ' -.-', 'dottedarrow': ' -.->'}
404        link_txt = '\n    ' + str(link[0].val) + link_t[link[1].val]
405        if len(link) == 4:
406            link_txt += '|' + link[3].val + '|'
407        return link_txt + ' ' + str(link[2].val)
408
409    @staticmethod
410    def _fc_node(node):
411        shape_l = {'rectangle': '[', 'roundedge': '(', 'stadium': '(['}
412        shape_r = {'rectangle': ']', 'roundedge': ')', 'stadium': '])'}
413        return '\n    ' + node.name + shape_l[node[0].val] + '"' + \
414               node[1].val.replace('"', "'") + '"' + shape_r[node[0].val]
415
416    @staticmethod
417    def _er_diagram(ntv):
418        erentity = MermaidConnec._er_entity
419        errelation = MermaidConnec._er_relation
420        diag_txt = ''
421        erd = Ntv.obj(ntv.val)
422        for entity in erd['entity']:
423            diag_txt += erentity(entity)
424        for relation in erd['relationship']:
425            diag_txt += errelation(relation)
426        return diag_txt
427
428    @staticmethod
429    def _er_entity(entity):
430        ent_txt = '\n    ' + entity.name + ' {'
431        for att in entity:
432            ent_txt += '\n        ' + att[0].val + ' ' + att[1].val
433            if len(att) > 2:
434                if att[2].val in ('PK', 'FK', 'UK'):
435                    ent_txt += ' ' + att[2].val
436                else:
437                    ent_txt += ' "' + att[2].val + '"'
438            if len(att) > 3:
439                ent_txt += ' "' + att[3].val + '"'
440        return ent_txt + '\n    }'
441
442    @staticmethod
443    def _er_relation(rel):
444        rel_left = {'exactly one': ' ||', 'zero or one': ' |o',
445                    'zero or more': ' }o', 'one or more': ' }|'}
446        rel_right = {'exactly one': '|| ', 'zero or one': 'o| ',
447                     'zero or more': 'o{ ', 'one or more': '|{ '}
448        identif = {'identifying': '--', 'non-identifying': '..'}
449        rel_txt = '\n    ' + rel[0].val + rel_left[rel[1].val] + \
450            identif[rel[2].val] + rel_right[rel[3].val] + rel[4].val
451        if len(rel) > 5:
452            rel_txt += ' : ' + rel[5].val
453        return rel_txt
def from_csv(file_name, single_tab=True, dialect='excel', **fmtparams):
41def from_csv(file_name, single_tab=True, dialect='excel', **fmtparams):
42    ''' return a 'tab' NtvSingle from a csv file
43
44    *parameters*
45
46    - **file_name** : name of the csv file
47    - **single_tab** : boolean (default True) - if True return a 'tab' NtvSingle,
48    else return a NtvSet.
49    - **dialect, fmtparams** : parameters of csv.DictReader object'''
50    with open(file_name, newline='') as csvfile:
51        reader = csv.DictReader(csvfile, dialect=dialect, **fmtparams)
52        names = reader.fieldnames
53        list_ntv_value = [[] for nam in names]
54        for row in reader:
55            for ind_field, val in enumerate(list(row.values())):
56                list_ntv_value[ind_field].append(json.loads(val))
57    list_ntv = []
58    for ind_field, field in enumerate(names):
59        list_ntv.append(
60            NtvList(list_ntv_value[ind_field], *Ntv.from_obj_name(field)[:2]))
61    if single_tab:
62        return NtvSingle(NtvList(list_ntv, None, None).to_obj(), None, 'tab')
63    return NtvList(list_ntv, None, None)

return a 'tab' NtvSingle from a csv file

parameters

  • file_name : name of the csv file
  • single_tab : boolean (default True) - if True return a 'tab' NtvSingle, else return a NtvSet.
  • dialect, fmtparams : parameters of csv.DictReader object
def to_csv( file_name, ntv, *args, restval='', extrasaction='raise', dialect='excel', **kwds):
66def to_csv(file_name, ntv, *args, restval='', extrasaction='raise', dialect='excel', **kwds):
67    ''' convert a 'tab' NtvSingle into csv file and return the file name
68
69    *parameters*
70
71    - **file_name** : name of the csv file
72    - **ntv** : 'tab' NtvSingle to convert
73    - **args, restval, extrasaction, dialect, kwds** : parameters of csv.DictWriter object'''
74    if isinstance(ntv, NtvSingle):
75        ntv_set = Ntv.obj(ntv.ntv_value)
76    else:
77        ntv_set = ntv
78    list_ntv = [Ntv.obj(field) for field in ntv_set]
79    fieldnames = [ntv_field.json_name(string=True) for ntv_field in list_ntv]
80    with open(file_name, 'w', newline='') as csvfile:
81        writer = csv.DictWriter(csvfile, fieldnames=fieldnames, restval=restval,
82                                extrasaction=extrasaction, dialect=dialect, *args, **kwds)
83        writer.writeheader()
84        for i in range(len(list_ntv[0])):
85            writer.writerow({name: field_ntv[i].to_obj(field_ntv.ntv_type, encoded=True)
86                             for name, field_ntv in zip(fieldnames, list_ntv)})
87    return file_name

convert a 'tab' NtvSingle into csv file and return the file name

parameters

  • file_name : name of the csv file
  • ntv : 'tab' NtvSingle to convert
  • args, restval, extrasaction, dialect, kwds : parameters of csv.DictWriter object
class ShapelyConnec(json_ntv.ntv_util.NtvConnector):
 90class ShapelyConnec(NtvConnector):
 91    '''NTV connector for geographic location'''
 92
 93    clas_obj = 'geometry'
 94    clas_typ = 'geometry'
 95
 96    @staticmethod
 97    def to_obj_ntv(ntv_value, **kwargs):
 98        ''' convert ntv_value into a shapely geometry object defined by 'type_geo'.
 99
100        *Parameters*
101
102        - **type_geo** : type of geometry (point, multipoint, line, multiline',
103        polygon, multipolygon)
104        - **ntv_value** : array - coordinates'''
105        from shapely import geometry
106        type_geo = ShapelyConnec.type_geo(ntv_value) if not 'type_geo' in kwargs \
107            or kwargs['type_geo'] == 'geometry' else kwargs['type_geo']
108        return geometry.shape({"type": type_geo, "coordinates": ntv_value})
109
110    @staticmethod
111    def to_json_ntv(value, name=None, typ=None):
112        ''' convert NTV object (value, name, type) into NTV json (json-value, name, type).
113
114        *Parameters*
115
116        - **typ** : string (default None) - NTV type of geometry (point, multipoint,
117        line, multiline', polygon, multipolygon),
118        - **name** : string (default None) - name of the NTV object
119        - **value** : shapely geometry'''
120        return (Ntv._listed(value.__geo_interface__['coordinates']), name, typ)
121
122    @staticmethod
123    def to_coord(geom):
124        ''' convert shapely geometry into geojson coordinates.'''
125        return Ntv._listed(geom.__geo_interface__['coordinates'])
126
127    @staticmethod
128    def to_geojson(geom):
129        ''' convert shapely geometry into geojson string'''
130        return json.dumps(geom.__geo_interface__)
131
132    @staticmethod
133    def from_geojson(geojson):
134        ''' convert geojson string into shapely geometry.'''
135        from shapely import geometry
136        return geometry.shape(json.loads(geojson))
137    
138    @staticmethod 
139    def to_geometry(value):
140        '''convert geojson coordinates into shapely geometry'''
141        return ShapelyConnec.to_obj_ntv(value, type_geo=ShapelyConnec.type_geo(value))
142    
143    @staticmethod 
144    def type_geo(value):
145        '''return geometry type of the value'''
146        if not value or not isinstance(value, list):
147            return 'not a geometry'
148        val = value[0]
149        if not isinstance(val, list):
150            return 'point'
151        val = val[0]
152        if not isinstance(val, list):
153            return 'line'        
154        return 'polygon'

NTV connector for geographic location

@staticmethod
def to_obj_ntv(ntv_value, **kwargs):
 96    @staticmethod
 97    def to_obj_ntv(ntv_value, **kwargs):
 98        ''' convert ntv_value into a shapely geometry object defined by 'type_geo'.
 99
100        *Parameters*
101
102        - **type_geo** : type of geometry (point, multipoint, line, multiline',
103        polygon, multipolygon)
104        - **ntv_value** : array - coordinates'''
105        from shapely import geometry
106        type_geo = ShapelyConnec.type_geo(ntv_value) if not 'type_geo' in kwargs \
107            or kwargs['type_geo'] == 'geometry' else kwargs['type_geo']
108        return geometry.shape({"type": type_geo, "coordinates": ntv_value})

convert ntv_value into a shapely geometry object defined by 'type_geo'.

Parameters

  • type_geo : type of geometry (point, multipoint, line, multiline', polygon, multipolygon)
  • ntv_value : array - coordinates
@staticmethod
def to_json_ntv(value, name=None, typ=None):
110    @staticmethod
111    def to_json_ntv(value, name=None, typ=None):
112        ''' convert NTV object (value, name, type) into NTV json (json-value, name, type).
113
114        *Parameters*
115
116        - **typ** : string (default None) - NTV type of geometry (point, multipoint,
117        line, multiline', polygon, multipolygon),
118        - **name** : string (default None) - name of the NTV object
119        - **value** : shapely geometry'''
120        return (Ntv._listed(value.__geo_interface__['coordinates']), name, typ)

convert NTV object (value, name, type) into NTV json (json-value, name, type).

Parameters

  • typ : string (default None) - NTV type of geometry (point, multipoint, line, multiline', polygon, multipolygon),
  • name : string (default None) - name of the NTV object
  • value : shapely geometry
@staticmethod
def to_coord(geom):
122    @staticmethod
123    def to_coord(geom):
124        ''' convert shapely geometry into geojson coordinates.'''
125        return Ntv._listed(geom.__geo_interface__['coordinates'])

convert shapely geometry into geojson coordinates.

@staticmethod
def to_geojson(geom):
127    @staticmethod
128    def to_geojson(geom):
129        ''' convert shapely geometry into geojson string'''
130        return json.dumps(geom.__geo_interface__)

convert shapely geometry into geojson string

@staticmethod
def from_geojson(geojson):
132    @staticmethod
133    def from_geojson(geojson):
134        ''' convert geojson string into shapely geometry.'''
135        from shapely import geometry
136        return geometry.shape(json.loads(geojson))

convert geojson string into shapely geometry.

@staticmethod
def to_geometry(value):
138    @staticmethod 
139    def to_geometry(value):
140        '''convert geojson coordinates into shapely geometry'''
141        return ShapelyConnec.to_obj_ntv(value, type_geo=ShapelyConnec.type_geo(value))

convert geojson coordinates into shapely geometry

@staticmethod
def type_geo(value):
143    @staticmethod 
144    def type_geo(value):
145        '''return geometry type of the value'''
146        if not value or not isinstance(value, list):
147            return 'not a geometry'
148        val = value[0]
149        if not isinstance(val, list):
150            return 'point'
151        val = val[0]
152        if not isinstance(val, list):
153            return 'line'        
154        return 'polygon'

return geometry type of the value

Inherited Members
json_ntv.ntv_util.NtvConnector
castable
dic_obj
dic_type
connector
dic_connec
cast
uncast
is_json_class
is_json
keysfromderkeys
encode_coef
keysfromcoef
init_ntv_keys
class CborConnec(json_ntv.ntv_util.NtvConnector):
156class CborConnec(NtvConnector):
157    '''NTV connector for binary data'''
158
159    clas_obj = 'bytes'
160    clas_typ = '$cbor'
161
162    @staticmethod
163    def to_obj_ntv(ntv_value, **kwargs):
164        ''' convert json ntv_value into a binary CBOR object (no parameters).'''
165        import cbor2
166        return cbor2.dumps(ntv_value, datetime_as_timestamp=True,
167                           timezone=datetime.timezone.utc, canonical=False,
168                           date_as_datetime=True)
169
170    @staticmethod
171    def to_json_ntv(value, name=None, typ=None):
172        ''' convert NTV binary object (value, name, type) into NTV json (json-value, name, type).
173
174        *Parameters*
175
176        - **typ** : string (default None) - type of the NTV object,
177        - **name** : string (default None) - name of the NTV object
178        - **value** : binary data'''
179        import cbor2
180        return (cbor2.loads(value), name, typ)

NTV connector for binary data

@staticmethod
def to_obj_ntv(ntv_value, **kwargs):
162    @staticmethod
163    def to_obj_ntv(ntv_value, **kwargs):
164        ''' convert json ntv_value into a binary CBOR object (no parameters).'''
165        import cbor2
166        return cbor2.dumps(ntv_value, datetime_as_timestamp=True,
167                           timezone=datetime.timezone.utc, canonical=False,
168                           date_as_datetime=True)

convert json ntv_value into a binary CBOR object (no parameters).

@staticmethod
def to_json_ntv(value, name=None, typ=None):
170    @staticmethod
171    def to_json_ntv(value, name=None, typ=None):
172        ''' convert NTV binary object (value, name, type) into NTV json (json-value, name, type).
173
174        *Parameters*
175
176        - **typ** : string (default None) - type of the NTV object,
177        - **name** : string (default None) - name of the NTV object
178        - **value** : binary data'''
179        import cbor2
180        return (cbor2.loads(value), name, typ)

convert NTV binary object (value, name, type) into NTV json (json-value, name, type).

Parameters

  • typ : string (default None) - type of the NTV object,
  • name : string (default None) - name of the NTV object
  • value : binary data
Inherited Members
json_ntv.ntv_util.NtvConnector
castable
dic_obj
dic_type
connector
dic_connec
cast
uncast
is_json_class
is_json
keysfromderkeys
encode_coef
keysfromcoef
init_ntv_keys
class NfieldConnec(json_ntv.ntv_util.NtvConnector):
183class NfieldConnec(NtvConnector):
184    '''NTV connector for NTV Field data'''
185
186    clas_obj = 'Nfield'
187    clas_typ = 'field'
188
189    @staticmethod
190    def to_obj_ntv(ntv_value, **kwargs):
191        ''' convert json ntv_value into a NTV Field object (no parameters).'''
192        from observation.fields import Nfield
193        ntv = Ntv.obj(ntv_value)
194        return Nfield.from_ntv(ntv)
195
196    @staticmethod
197    def to_json_ntv(value, name=None, typ=None):
198        ''' convert NTV Field object (value, name, type) into NTV json (json-value, name, type).
199
200        *Parameters*
201
202        - **typ** : string (default None) - type of the NTV object,
203        - **name** : string (default None) - name of the NTV object
204        - **value** : NTV Field values (default format)'''
205        return (value.to_ntv(name=True).to_obj(), name,
206                NfieldConnec.clas_typ if not typ else typ)

NTV connector for NTV Field data

@staticmethod
def to_obj_ntv(ntv_value, **kwargs):
189    @staticmethod
190    def to_obj_ntv(ntv_value, **kwargs):
191        ''' convert json ntv_value into a NTV Field object (no parameters).'''
192        from observation.fields import Nfield
193        ntv = Ntv.obj(ntv_value)
194        return Nfield.from_ntv(ntv)

convert json ntv_value into a NTV Field object (no parameters).

@staticmethod
def to_json_ntv(value, name=None, typ=None):
196    @staticmethod
197    def to_json_ntv(value, name=None, typ=None):
198        ''' convert NTV Field object (value, name, type) into NTV json (json-value, name, type).
199
200        *Parameters*
201
202        - **typ** : string (default None) - type of the NTV object,
203        - **name** : string (default None) - name of the NTV object
204        - **value** : NTV Field values (default format)'''
205        return (value.to_ntv(name=True).to_obj(), name,
206                NfieldConnec.clas_typ if not typ else typ)

convert NTV Field object (value, name, type) into NTV json (json-value, name, type).

Parameters

  • typ : string (default None) - type of the NTV object,
  • name : string (default None) - name of the NTV object
  • value : NTV Field values (default format)
Inherited Members
json_ntv.ntv_util.NtvConnector
castable
dic_obj
dic_type
connector
dic_connec
cast
uncast
is_json_class
is_json
keysfromderkeys
encode_coef
keysfromcoef
init_ntv_keys
class SfieldConnec(json_ntv.ntv_util.NtvConnector):
209class SfieldConnec(NtvConnector):
210    '''NTV connector for simple Field data'''
211
212    clas_obj = 'Sfield'
213    clas_typ = 'field'
214
215    @staticmethod
216    def to_obj_ntv(ntv_value, **kwargs):
217        ''' convert json ntv_value into a simple Field object (no parameters).'''
218        from observation.fields import Sfield
219        ntv = Ntv.obj(ntv_value)
220        return Sfield.from_ntv(ntv)
221
222    @staticmethod
223    def to_json_ntv(value, name=None, typ=None):
224        ''' convert simple Field object (value, name, type) into NTV json (json-value, name, type).
225
226        *Parameters*
227
228        - **typ** : string (default None) - type of the NTV object,
229        - **name** : string (default None) - name of the NTV object
230        - **value** : simple Field values (default format)'''
231        return (value.to_ntv(name=True).to_obj(), name,
232                NfieldConnec.clas_typ if not typ else typ)

NTV connector for simple Field data

@staticmethod
def to_obj_ntv(ntv_value, **kwargs):
215    @staticmethod
216    def to_obj_ntv(ntv_value, **kwargs):
217        ''' convert json ntv_value into a simple Field object (no parameters).'''
218        from observation.fields import Sfield
219        ntv = Ntv.obj(ntv_value)
220        return Sfield.from_ntv(ntv)

convert json ntv_value into a simple Field object (no parameters).

@staticmethod
def to_json_ntv(value, name=None, typ=None):
222    @staticmethod
223    def to_json_ntv(value, name=None, typ=None):
224        ''' convert simple Field object (value, name, type) into NTV json (json-value, name, type).
225
226        *Parameters*
227
228        - **typ** : string (default None) - type of the NTV object,
229        - **name** : string (default None) - name of the NTV object
230        - **value** : simple Field values (default format)'''
231        return (value.to_ntv(name=True).to_obj(), name,
232                NfieldConnec.clas_typ if not typ else typ)

convert simple Field object (value, name, type) into NTV json (json-value, name, type).

Parameters

  • typ : string (default None) - type of the NTV object,
  • name : string (default None) - name of the NTV object
  • value : simple Field values (default format)
Inherited Members
json_ntv.ntv_util.NtvConnector
castable
dic_obj
dic_type
connector
dic_connec
cast
uncast
is_json_class
is_json
keysfromderkeys
encode_coef
keysfromcoef
init_ntv_keys
class NdatasetConnec(json_ntv.ntv_util.NtvConnector):
235class NdatasetConnec(NtvConnector):
236    '''NTV connector for NTV Dataset data'''
237
238    clas_obj = 'Ndataset'
239    clas_typ = 'tab'
240
241    @staticmethod
242    def to_obj_ntv(ntv_value, **kwargs):
243        ''' convert json ntv_value into a NTV Dataset object (no parameters).'''
244        from observation.datasets import Ndataset
245
246        ntv = Ntv.obj(ntv_value)
247        return Ndataset.from_ntv(ntv)
248
249    @staticmethod
250    def to_json_ntv(value, name=None, typ=None):
251        ''' convert NTV Dataset object (value, name, type) into NTV json (json-value, name, type).
252
253        *Parameters*
254
255        - **typ** : string (default None) - type of the NTV object,
256        - **name** : string (default None) - name of the NTV object
257        - **value** : NTV Dataset values'''
258        return (value.to_ntv().to_obj(), name,
259                NdatasetConnec.clas_typ if not typ else typ)

NTV connector for NTV Dataset data

@staticmethod
def to_obj_ntv(ntv_value, **kwargs):
241    @staticmethod
242    def to_obj_ntv(ntv_value, **kwargs):
243        ''' convert json ntv_value into a NTV Dataset object (no parameters).'''
244        from observation.datasets import Ndataset
245
246        ntv = Ntv.obj(ntv_value)
247        return Ndataset.from_ntv(ntv)

convert json ntv_value into a NTV Dataset object (no parameters).

@staticmethod
def to_json_ntv(value, name=None, typ=None):
249    @staticmethod
250    def to_json_ntv(value, name=None, typ=None):
251        ''' convert NTV Dataset object (value, name, type) into NTV json (json-value, name, type).
252
253        *Parameters*
254
255        - **typ** : string (default None) - type of the NTV object,
256        - **name** : string (default None) - name of the NTV object
257        - **value** : NTV Dataset values'''
258        return (value.to_ntv().to_obj(), name,
259                NdatasetConnec.clas_typ if not typ else typ)

convert NTV Dataset object (value, name, type) into NTV json (json-value, name, type).

Parameters

  • typ : string (default None) - type of the NTV object,
  • name : string (default None) - name of the NTV object
  • value : NTV Dataset values
Inherited Members
json_ntv.ntv_util.NtvConnector
castable
dic_obj
dic_type
connector
dic_connec
cast
uncast
is_json_class
is_json
keysfromderkeys
encode_coef
keysfromcoef
init_ntv_keys
class SdatasetConnec(json_ntv.ntv_util.NtvConnector):
262class SdatasetConnec(NtvConnector):
263    '''NTV connector for simple Dataset data'''
264
265    clas_obj = 'Sdataset'
266    clas_typ = 'tab'
267
268    @staticmethod
269    def to_obj_ntv(ntv_value, **kwargs):
270        ''' convert json ntv_value into a simple Dataset object (no parameters).'''
271        from observation.datasets import Sdataset
272
273        ntv = Ntv.obj(ntv_value)
274        return Sdataset.from_ntv(ntv)
275
276    @staticmethod
277    def to_json_ntv(value, name=None, typ=None):
278        ''' convert simple Dataset object (value, name, type) into NTV json
279        (json-value, name, type).
280
281        *Parameters*
282
283        - **typ** : string (default None) - type of the NTV object,
284        - **name** : string (default None) - name of the NTV object
285        - **value** : simple Dataset values'''
286        return (value.to_ntv().to_obj(), name,
287                SdatasetConnec.clas_typ if not typ else typ)

NTV connector for simple Dataset data

@staticmethod
def to_obj_ntv(ntv_value, **kwargs):
268    @staticmethod
269    def to_obj_ntv(ntv_value, **kwargs):
270        ''' convert json ntv_value into a simple Dataset object (no parameters).'''
271        from observation.datasets import Sdataset
272
273        ntv = Ntv.obj(ntv_value)
274        return Sdataset.from_ntv(ntv)

convert json ntv_value into a simple Dataset object (no parameters).

@staticmethod
def to_json_ntv(value, name=None, typ=None):
276    @staticmethod
277    def to_json_ntv(value, name=None, typ=None):
278        ''' convert simple Dataset object (value, name, type) into NTV json
279        (json-value, name, type).
280
281        *Parameters*
282
283        - **typ** : string (default None) - type of the NTV object,
284        - **name** : string (default None) - name of the NTV object
285        - **value** : simple Dataset values'''
286        return (value.to_ntv().to_obj(), name,
287                SdatasetConnec.clas_typ if not typ else typ)

convert simple Dataset object (value, name, type) into NTV json (json-value, name, type).

Parameters

  • typ : string (default None) - type of the NTV object,
  • name : string (default None) - name of the NTV object
  • value : simple Dataset values
Inherited Members
json_ntv.ntv_util.NtvConnector
castable
dic_obj
dic_type
connector
dic_connec
cast
uncast
is_json_class
is_json
keysfromderkeys
encode_coef
keysfromcoef
init_ntv_keys
class MermaidConnec(json_ntv.ntv_util.NtvConnector):
289class MermaidConnec(NtvConnector):
290    '''NTV connector for Mermaid diagram'''
291
292    clas_obj = 'Mermaid'
293    clas_typ = '$mermaid'
294
295    @staticmethod
296    def to_obj_ntv(ntv_value, **kwargs):
297        ''' convert ntv_value into a mermaid flowchart
298
299        *Parameters*
300
301        - **title**: String (default '') - title of the flowchart
302        - **disp**: Boolean (default False) - if true, return a display else return
303        a mermaid text diagram
304        - **row**: Boolean (default False) - if True, add the node row
305        - **leaves**: Boolean (default False) - if True, add the leaf row
306        '''
307        from base64 import b64encode
308        from IPython.display import Image, display
309
310        option = {'title': '', 'disp': False, 'row': False,
311                  'leaves': False} | kwargs
312        diagram = MermaidConnec.diagram
313        link = MermaidConnec._mermaid_link
314        ntv = Ntv.obj(ntv_value)
315        node_link = {'nodes': [], 'links': []}
316        dic_node = {}
317        if option['leaves']:
318            nodes = [node for node in NtvTree(
319                ntv) if not isinstance(node.val, list)]
320            dic_node = {node: row for row, node in enumerate(nodes)}
321        link(ntv, None, node_link, option['row'], dic_node, None)
322        mermaid_json = {option['title'] + ':$flowchart': {
323            'orientation': 'top-down',
324            'node::': {node[0]: node[1] for node in node_link['nodes']},
325            'link::': node_link['links']}}
326        if option['disp']:
327            return display(Image(url="https://mermaid.ink/img/" +
328                                 b64encode(diagram(mermaid_json).encode("ascii")).decode("ascii")))
329        return diagram(mermaid_json)
330
331    @staticmethod
332    def diagram(json_diag):
333        '''create a mermaid code from a mermaid json'''
334        ntv = Ntv.obj(json_diag)
335        erdiagram = MermaidConnec._er_diagram
336        flowchart = MermaidConnec._flowchart
337        diag_type = ntv.type_str[1:]
338        diag_txt = '---\ntitle: ' + ntv.name + '\n---\n' if ntv.name else ''
339        diag_txt += diag_type
340        match diag_type:
341            case 'erDiagram':
342                diag_txt += erdiagram(ntv)
343            case 'flowchart':
344                diag_txt += flowchart(ntv)
345        return diag_txt
346
347    @staticmethod
348    def _mermaid_node(ntv, def_typ_str, num, dic_node, ind):
349        '''create and return a node'''
350        j_name, j_sep, j_type = ntv.json_name(def_typ_str)
351        name = ''
352        if j_name:
353            name += '<b>' + j_name + '</b>\n'
354        if j_type:
355            name += j_type + '\n'
356        if ntv in dic_node:
357            num += ' ' + str(dic_node[ntv])
358        if num:
359            name += '<i>' + num + '</i>\n'
360        elif isinstance(ntv, NtvSingle):
361            if isinstance(ntv.val, str):
362                name += '<i>' + ntv.val + '</i>\n'
363            else:
364                name += '<i>' + json.dumps(ntv.val) + '</i>\n'
365            return [ntv.pointer(index=True, item_idx=ind).json(default='/'), 
366                    ['rectangle', name[:-1]]]
367        if not name:
368            name = '<b>::</b>\n'
369        name = name.replace('"', "'")
370        return [ntv.pointer(index=True, item_idx=ind).json(default='/'), 
371                ['roundedge', name[:-1]]]
372
373    @staticmethod
374    def _mermaid_link(ntv, def_typ_str, node_link, row, dic_node, ind):
375        '''add nodes and links from ntv in node_link '''
376        num = str(len(node_link['nodes'])) if row else ''
377        node_link['nodes'].append(MermaidConnec._mermaid_node(
378            ntv, def_typ_str, num, dic_node, ind))
379        if isinstance(ntv, NtvList):
380            for ind, ntv_val in enumerate(ntv):
381                MermaidConnec._mermaid_link(ntv_val, ntv.type_str,
382                                            node_link, row, dic_node, ind)
383                node_link['links'].append(
384                    [ntv.pointer(index=True).json(default='/'), 'normalarrow',
385                     ntv_val.pointer(index=True, item_idx=ind).json(default='/')])
386
387    @staticmethod
388    def _flowchart(ntv):
389        orientation = {'top-down': 'TD', 'top-bottom': 'TB',
390                       'bottom-top': 'BT', 'right-left': 'RL', 'left-right': 'LR'}
391        fcnode = MermaidConnec._fc_node
392        fclink = MermaidConnec._fc_link
393        flc = Ntv.obj(ntv.val)
394        diag_txt = ' ' + orientation[flc['orientation'].val]
395        for node in flc['node']:
396            diag_txt += fcnode(node)
397        for link in flc['link']:
398            diag_txt += fclink(link)
399        return diag_txt + '\n'
400
401    @staticmethod
402    def _fc_link(link):
403        link_t = {'normal': ' ---', 'normalarrow': ' -->',
404                  'dotted': ' -.-', 'dottedarrow': ' -.->'}
405        link_txt = '\n    ' + str(link[0].val) + link_t[link[1].val]
406        if len(link) == 4:
407            link_txt += '|' + link[3].val + '|'
408        return link_txt + ' ' + str(link[2].val)
409
410    @staticmethod
411    def _fc_node(node):
412        shape_l = {'rectangle': '[', 'roundedge': '(', 'stadium': '(['}
413        shape_r = {'rectangle': ']', 'roundedge': ')', 'stadium': '])'}
414        return '\n    ' + node.name + shape_l[node[0].val] + '"' + \
415               node[1].val.replace('"', "'") + '"' + shape_r[node[0].val]
416
417    @staticmethod
418    def _er_diagram(ntv):
419        erentity = MermaidConnec._er_entity
420        errelation = MermaidConnec._er_relation
421        diag_txt = ''
422        erd = Ntv.obj(ntv.val)
423        for entity in erd['entity']:
424            diag_txt += erentity(entity)
425        for relation in erd['relationship']:
426            diag_txt += errelation(relation)
427        return diag_txt
428
429    @staticmethod
430    def _er_entity(entity):
431        ent_txt = '\n    ' + entity.name + ' {'
432        for att in entity:
433            ent_txt += '\n        ' + att[0].val + ' ' + att[1].val
434            if len(att) > 2:
435                if att[2].val in ('PK', 'FK', 'UK'):
436                    ent_txt += ' ' + att[2].val
437                else:
438                    ent_txt += ' "' + att[2].val + '"'
439            if len(att) > 3:
440                ent_txt += ' "' + att[3].val + '"'
441        return ent_txt + '\n    }'
442
443    @staticmethod
444    def _er_relation(rel):
445        rel_left = {'exactly one': ' ||', 'zero or one': ' |o',
446                    'zero or more': ' }o', 'one or more': ' }|'}
447        rel_right = {'exactly one': '|| ', 'zero or one': 'o| ',
448                     'zero or more': 'o{ ', 'one or more': '|{ '}
449        identif = {'identifying': '--', 'non-identifying': '..'}
450        rel_txt = '\n    ' + rel[0].val + rel_left[rel[1].val] + \
451            identif[rel[2].val] + rel_right[rel[3].val] + rel[4].val
452        if len(rel) > 5:
453            rel_txt += ' : ' + rel[5].val
454        return rel_txt

NTV connector for Mermaid diagram

@staticmethod
def to_obj_ntv(ntv_value, **kwargs):
295    @staticmethod
296    def to_obj_ntv(ntv_value, **kwargs):
297        ''' convert ntv_value into a mermaid flowchart
298
299        *Parameters*
300
301        - **title**: String (default '') - title of the flowchart
302        - **disp**: Boolean (default False) - if true, return a display else return
303        a mermaid text diagram
304        - **row**: Boolean (default False) - if True, add the node row
305        - **leaves**: Boolean (default False) - if True, add the leaf row
306        '''
307        from base64 import b64encode
308        from IPython.display import Image, display
309
310        option = {'title': '', 'disp': False, 'row': False,
311                  'leaves': False} | kwargs
312        diagram = MermaidConnec.diagram
313        link = MermaidConnec._mermaid_link
314        ntv = Ntv.obj(ntv_value)
315        node_link = {'nodes': [], 'links': []}
316        dic_node = {}
317        if option['leaves']:
318            nodes = [node for node in NtvTree(
319                ntv) if not isinstance(node.val, list)]
320            dic_node = {node: row for row, node in enumerate(nodes)}
321        link(ntv, None, node_link, option['row'], dic_node, None)
322        mermaid_json = {option['title'] + ':$flowchart': {
323            'orientation': 'top-down',
324            'node::': {node[0]: node[1] for node in node_link['nodes']},
325            'link::': node_link['links']}}
326        if option['disp']:
327            return display(Image(url="https://mermaid.ink/img/" +
328                                 b64encode(diagram(mermaid_json).encode("ascii")).decode("ascii")))
329        return diagram(mermaid_json)

convert ntv_value into a mermaid flowchart

Parameters

  • title: String (default '') - title of the flowchart
  • disp: Boolean (default False) - if true, return a display else return a mermaid text diagram
  • row: Boolean (default False) - if True, add the node row
  • leaves: Boolean (default False) - if True, add the leaf row
@staticmethod
def diagram(json_diag):
331    @staticmethod
332    def diagram(json_diag):
333        '''create a mermaid code from a mermaid json'''
334        ntv = Ntv.obj(json_diag)
335        erdiagram = MermaidConnec._er_diagram
336        flowchart = MermaidConnec._flowchart
337        diag_type = ntv.type_str[1:]
338        diag_txt = '---\ntitle: ' + ntv.name + '\n---\n' if ntv.name else ''
339        diag_txt += diag_type
340        match diag_type:
341            case 'erDiagram':
342                diag_txt += erdiagram(ntv)
343            case 'flowchart':
344                diag_txt += flowchart(ntv)
345        return diag_txt

create a mermaid code from a mermaid json

Inherited Members
json_ntv.ntv_util.NtvConnector
castable
dic_obj
dic_type
connector
dic_connec
to_json_ntv
cast
uncast
is_json_class
is_json
keysfromderkeys
encode_coef
keysfromcoef
init_ntv_keys