X3D to JSON Stylesheet Converter |
The X3D to JSON stylesheet converts .x3d XML to .json, supporting the forthcoming JSON Encoding for X3D Graphics.
Overview | Goals | Data Types | Design Patterns | Design Correspondences | Examples | Issues | Options | References | Related Work | Tools | Contact
Status: developmental work is mature and provides full coverage. Design pattern being assessed by X3D community.
This work supports X3D JSON Encoding efforts by the X3D Working Group. It is summarized in the Web3D 2016 paper "A JSON Encoding for X3D".
The Web3D Consortium standards strategy has the fundamental objective to enable the open publishing of interactive 3D graphics models on the Web, enabling real-time 3D communication. Web3D carefully improves and evolves X3D Graphics and related standards while maintaining long-term archival stability.
JavaScript Object Notation (JSON) is "a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language". (from json.org)
X3D scenes can be encoded in various encoding formats. In order to consistently take advantage of JSON capabilities, the X3D Working Group is preparing a new ISO/IEC 19776-5 specification X3D JSON Encoding.
The X3D JSON Encoding needs to meet multiple interoperability requirements:
The X3D abstract specification (ISO/IEC 19775-1) governs X3D semantics and presentation for all scene encodings. Thus no new X3D functionality for graphics rendering or scene interaction are needed for the X3D JSON encoding.
JSON defines a native JavaScript object that can be parsed directly from a JSON string. Once loaded, the resulting object tree can be used to provide a renderable presentation along with behavior of the scene graph.
Interpreting the JSON and rendering the X3D scene graph is typically an independent decision for a given JavaScript library of interest. The JSON representation is only meant to provide the scene graph for appropriate initialization in the 3D engine, and perhaps optionally export model state at a given moment if desired.
The forthcoming X3D JSON Encoding (ISO 19776-5) specification needs to fully define everything representable in a scene graph defined by the X3D Abstract Specification. Full expression of all scene graph information is commonly referred to as the "round trippable" property. This round-trippable requirement for functional equivalence is shared by all X3D encodings: XML .x3d, ClassicVRML .x3dv, Compressed Binary .x3db. Authors can thus use any X3D encoding of interest interchangeably.
Programming goals for X3D JSON include:
require()
in order to use the same package management as code and assets
in the rest of the JavaScript application.
Note that the features for representing an entire X3D scene using JSON are quite different than the X3D language binding for ECMAScript, which describes linking or embedding JavaScript source code within a Script node as part of an X3D scene.
Functional requirements for X3D JSON include:
eval()
method needs to be applied.
Use cases for X3D JSON include:
JSON has two primary data structures: objects and arrays. Aligning X3D scene graphs well with these data structures is the essence of this design process. From the json.org site:
Curiously, other XML-based languages have applied multiple different approaches to mapping XML document models to JSON object models. In order to consistently reconcile conceptual overlaps, the following nomenclature conventions are been used.
Nomenclature comparison: X3D, XML, JSON | ||
---|---|---|
X3D scene graph | XML encoding for X3D | JSON encoding for X3D |
X3D nodes | XML elements | JSON objects |
X3D node name | XML tag (open/close or singleton tags) | JSON object name |
Scene-graph structures/statements | XML elements | JSON objects |
X3D simple-type fields | XML attributes |
prepend @ sign to field name as JSON string
|
X3D MFNode child nodes | Single ordered array of sibling elements | One or more JSON strings for each [array of JSON objects] |
X3D SFNode/MFNode field names |
containerField value
Example: containerField='children'
|
Prepend - hyphen to JSON string for field name,
do not include as a separate @containerField attribute
Example: "-children"
|
Comments |
<!-- XML comment -->
|
Special string prefix: "#comment" for single-object comments
|
Embedded source code for
Script, ShaderPart and ShaderProgram nodes |
CDATA (Character DATA) section
<[CDATA[ "world wild Web!" ]]>
|
"#sourceCode" string array containing original code, typically not escaped.
(previously named #sourceText )
|
TODO: add notes contrasting document models to object models.
It is important to get the X3D JSON design pattern correct. Here are possible approaches for an example set of four adjacent ROUTE statements.
Source excerpts from scene OrigamiCranes.x3d | |
---|---|
<Group DEF='AnimatedView'> <Viewpoint DEF='MovingPov' description='Rotating Viewpoint'/> <TimeSensor DEF='PovClock' cycleInterval='60' loop='true'/> <PositionInterpolator DEF='MovingPovLocation' key='0 0.125 0.25 0.375 0.5 0.625 0.75 0.875 1' keyValue='0 0 3 etc.'/> <ROUTE fromField='fraction_changed' fromNode='PovClock' toField='set_fraction' toNode='MovingPovRotation'/> <ROUTE fromField='fraction_changed' fromNode='PovClock' toField='set_fraction' toNode='MovingPovLocation'/> <OrientationInterpolator DEF='MovingPovRotation' key='0 0.125 0.25 0.375 0.5 0.625 0.75 0.875 1' keyValue='0 1 0 0 etc.'/> <ROUTE fromField='value_changed' fromNode='MovingPovRotation' toField='set_orientation' toNode='MovingPov'/> <ROUTE fromField='value_changed' fromNode='MovingPovLocation' toField='position' toNode='MovingPov'/> </Group> |
For comparison, please look at the different approaches that follow. Each pattern encodes these same four ROUTEs.
The pattern on the left is important from a JSON perspective, because it avoids JSON validation errors. This is because it avoids object-model ambiguity problems that occur when multiple key names are repeated for a parent object.
The pattern in the third column (showing the four ROUTEs in context) was evaluated as the best solution for preserving ROUTE ordering within an X3D scene.
Single key for contained objects: valid JSON |
Repeating keys for multiple objects: invalid JSON |
Common -children key for ROUTE objects: valid JSON. Approved. |
---|---|---|
"ROUTE":[ { "@fromField":"fraction_changed", "@fromNode":"PovClock", "@toField":"set_fraction", "@toNode":"MovingPovRotation" }, { "@fromField":"fraction_changed", "@fromNode":"PovClock", "@toField":"set_fraction", "@toNode":"MovingPovLocation" }, { "@fromField":"value_changed", "@fromNode":"MovingPovRotation", "@toField":"set_orientation", "@toNode":"MovingPov" }, { "@fromField":"value_changed", "@fromNode":"MovingPovLocation", "@toField":"position", "@toNode":"MovingPov" } ] Advantages: terse, clear. Disadvantages: ordering of ROUTE statements is lost, relative to other children nodes. ROUTEs are placed at the end, only a partial order is retained. The downside of bundling the four ROUTEs together is that these statements might not have appeared side-by-side in the original X3D scene. The order of the sequence from first to last might be unchanged, but these ROUTE statements might appear before & after other nodes when compared to the original scene. For this approach, moving ROUTEs means that exact literal round-trippability with the original scene is not always possible. Nevertheless functional equivalence of rendering and behavior for the scene appears to be possible. Local partial sorts can limit any reshuffling to sorting by field, leaving the original first-to-last sequence of occurrence unchanged. |
"ROUTE": { "@fromField":"fraction_changed", "@fromNode":"PovClock", "@toField":"set_fraction", "@toNode":"MovingPovRotation" }, "ROUTE": { "@fromField":"fraction_changed", "@fromNode":"PovClock", "@toField":"set_fraction", "@toNode":"MovingPovLocation" }, "ROUTE": { "@fromField":"value_changed", "@fromNode":"MovingPovRotation", "@toField":"set_orientation", "@toNode":"MovingPov" }, "ROUTE": { "@fromField":"value_changed", "@fromNode":"MovingPovLocation", "@toField":"position", "@toNode":"MovingPov" } Advantages: terse, clear. Disadvantages: invalid JSON object since the ROUTE key is used multiple times. |
{ "Group": { "@DEF":"AnimatedView", "-children":[ { "Viewpoint": { "@DEF":"MovingPov", "@description":"Rotating Viewpoint" } }, { "TimeSensor": { "@DEF":"PovClock", "@cycleInterval":60, "@loop":true } }, { "PositionInterpolator": { "@DEF":"MovingPovLocation", "@key":[0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1], "@keyValue":[0,0,3,3,0,2,3,0,2,0,0,3,0,0,3,-3,0,2,-3,0,2,0,0,3,0,0,3] } }, { "ROUTE": { "@fromField":"fraction_changed", "@fromNode":"PovClock", "@toField":"set_fraction", "@toNode":"MovingPovLocation" } }, { "ROUTE": { "@fromField":"value_changed", "@fromNode":"MovingPovLocation", "@toField":"position", "@toNode":"MovingPov" } }, { "OrientationInterpolator": { "@DEF":"MovingPovRotation", "@key":[0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1], "@keyValue":[0,1,0,0,0,1,0,0.982794,etc.] } }, { "ROUTE": { "@fromField":"fraction_changed", "@fromNode":"PovClock", "@toField":"set_fraction", "@toNode":"MovingPovRotation" } }, { "ROUTE": { "@fromField":"value_changed", "@fromNode":"MovingPovRotation", "@toField":"set_orientation", "@toNode":"MovingPov" } } ] } }, Advantages: terse, clear. Ordering of nodes in the original scene is nearly always preserved. |
Some special X3D semantics must always be observed. For example, X3D requires each ROUTE must appear after the DEF nodes it refers to. (DEF/USE name identifiers for X3D nodes have type ID/IDREF in XML, which does not provide ordering constraints.) Preserving order with other peer nodes avoids creating any new problems for a scene.
Typically most elements are children
nodes, but that is not always the case.
Since a ROUTE is allowed to appear almost anywhere in the scene graph, one extra precaution is necessary.
For acceptable local reordering of ROUTEs that appear within a Shape, or within other nodes that are outside of a regular -children context, the
"-children":{ROUTE}
constructs are placed after any other sibling nodes.
These design patterns for X3D JSON include the following correspondences.
@containerField
attribute is not listed separately.
@attributeName
for attributes -fieldName
for containerField names #comment
for comments (an allowed option, even though not natively supported by JSON) #sourceCode
preservation of character data (e.g. source code contained in a
Script,
ShaderPart
and
ShaderProgram
node)
"@transparency":1,
rather than
"@transparency":[1],
"-geometry": { "Sphere": { } }
#sourceCode
code
(for X3D
Script,
ShaderPart
and
ShaderProgram
nodes)
must follow JSON rules that demand replacement of line feeds as \n
literals and
tabs as \t
literals
(discussion).
A significant reduction in readability occurs but apparently is required.
A
stylesheet switch
allows an author to retain multiline strings without such obfuscation.
"X3D"
object is given a field such as "encoding":"UTF-8"
to indicate the scene author's expected encoding.
This expression of file encoding corresponds to the header statement syntax required for the
VRML97,
ClassicVRML
and
XML
file formats.
See the Issues list for additional changes under consideration.
The following tables illustrate how each of the major JSON constructs are correlated to X3D nodes, fields, statements and values.
JSON objects are typically an X3D node, or scene graph structure element. Note that each string matches an X3D field name and must be unique, allowing direct access to each field.
string : | value |
---|---|
X3D, head and Scene : | scene-graph structure elements |
simple-type field name : | attribute value |
containerField : | X3D nodes (XML elements) as JSON objects |
Test examples are essential for determining how the X3D JSON encoding can best meets authoring and library requirements.
Excerpted encodings of example X3D scene-graph fragments follow.
TODO: show continued conversion excerpts including nodes, attributes, comments, children nodes, X3D statements, Scripts, prototypes, fields, IS/connect.
Source excerpts, .x3d and .json | Notes |
---|---|
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.3//EN" "https://www.web3d.org/specifications/x3d-3.3.dtd"> <X3D profile='Immersive' version='3.3 xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.3.xsd'> <head></head> <Scene></Scene> </X3D> |
X3D, head and Scene are scene-graph structure statements. X3D X3D |
{ "X3D": { "@profile":"Immersive", "@version":3.3, "@xsd:noNamespaceSchemaLocation":"https://www.web3d.org/specifications/x3d-3.3.xsd", "head":{ }, "Scene":{ } } } |
XML header and DOCTYPE are omitted in the JSON encoding. X3D, head and Scene are JSON objects that contain arrays of JSON objects. Resolved: avoid wrapping the X3D object in [array brackets] since they are superfluous. |
Source excerpts, .x3d and .json | Notes |
---|---|
<head> <component level='1' name='CADGeometry'/> <component level='1' name='HAnim'/> <unit category='length' conversionFactor='0.9144' name='Yards'/> <unit category='angle' conversionFactor='0.0174532925167' name='Degrees'/> <meta content='TestJsonEncoding.x3d' name='title'/> <meta content='2 November 2015' name='modified'/> <meta content='TestJsonEncoding.json' name='reference'/> <!-- Here is a comment. --> </head> |
Note that this excerpt from an X3D scene only produces a valid JSON fragment because it does not include the parent X3D element. |
{ "X3D": { "head":{ { "component":[ { "@level":1, "@name":"CADGeometry" }, { "@level":1, "@name":"HAnim" } ] }, { "unit":[ { "@category":"length", "@conversionFactor":0.9144, "@name":"Yards" }, { "@category":"angle", "@conversionFactor":0.0174532925167, "@name":"Degrees" } ] }, { "meta":[ { "@content":"TestJsonEncoding.x3d", "@name":"title" }, { "@content":"2 November 2015", "@name":"modified" }, { "@content":"TestJsonEncoding.json", "@name":"reference" } ] }, { "#comment":"Here is a comment." } } } |
Note multiple statement elements are collected as objects, with each set of matching objects found under a single statement key. Comments are treated as -children objects, typically allowing them to appear individually instead of clumped under a single key. |
Source excerpts, .x3d and .json | Notes |
---|---|
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.3//EN" "https://www.web3d.org/specifications/x3d-3.3.dtd"> <X3D profile='Immersive' version='3.3' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.3.xsd'> <head> <meta content='HelloWorld.x3d' name='title'/> <meta content='Simple X3D scene example: Hello World!' name='description'/> <meta content='30 October 2000' name='created'/> <meta content='14 October 2015' name='modified'/> <meta content='Don Brutzman' name='creator'/> <meta content='HelloWorld.tall.png' name='Image'/> <meta content='http://en.wikipedia.org/wiki/Hello_world' name='reference'/> <meta content='https://en.wikipedia.org/wiki/Hello#.22Hello.2C_World.22_computer_program' name='reference'/> <meta content='https://en.wikipedia.org/wiki/"Hello,_World!"_program' name='reference'/> <meta content='http://en.wikibooks.org/w/index.php?title=Computer_Programming/Hello_world' name='reference'/> <meta content='http://www.HelloWorldExample.net' name='reference'/> <meta content='http://www.web3D.org' name='reference'/> <meta content='https://www.web3d.org/realtime-3d/news/internationalization-x3d' name='reference'/> <meta content='https://www.web3d.org/x3d/content/examples/HelloWorld.x3d' name='reference'/> <meta content='http://X3dGraphics.com/examples/X3dForAdvancedModeling/HelloWorldScenes' name='reference'/> <meta content='http://X3dGraphics.com/examples/X3dForWebAuthors/Chapter01-TechnicalOverview/HelloWorld.x3d' name='identifier'/> <meta content='https://www.web3d.org/x3d/content/examples/license.html' name='license'/> <meta content='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit' name='generator'/> <!-- Alternate encodings: VRML97, X3D ClassicVRML Encoding, X3D Compressed Binary Encoding (CBE), X3DOM, JSON --> <meta content='HelloWorld.wrl' name='reference'/> <meta content='HelloWorld.x3dv' name='reference'/> <meta content='HelloWorld.x3db' name='reference'/> <meta content='HelloWorld.xhtml' name='reference'/> <meta content='HelloWorld.json' name='reference'/> </head> <Scene> <!-- Example scene to illustrate X3D nodes and fields (XML elements and attributes) --> <WorldInfo title='Hello world!'/> <Group> <Viewpoint DEF='ViewUpClose' centerOfRotation='0 -1 0' description='Hello world!' position='0 -1 7'/> <Transform rotation='0 1 0 3'> <Shape> <Sphere/> <Appearance> <Material DEF='MaterialLightBlue' diffuseColor='0.1 0.5 1'/> <ImageTexture DEF='ImageCloudlessEarth' url='"earth-topo.png" "earth-topo.jpg" "earth-topo-small.gif" "https://www.web3d.org/x3d/content/examples/Basic/earth-topo.png" "https://www.web3d.org/x3d/content/examples/Basic/earth-topo.jpg" "https://www.web3d.org/x3d/content/examples/Basic/earth-topo-small.gif"'/> </Appearance> </Shape> </Transform> <Transform translation='0 -2 0'> <Shape> <Text DEF='TextMessage' string='"Hello" "world!"'> <FontStyle justify='"MIDDLE" "MIDDLE"'/> </Text> <Appearance> <Material USE='MaterialLightBlue'/> </Appearance> </Shape> </Transform> </Group> </Scene> </X3D> |
HelloWorld.x3d
source, |
Source excerpts, .x3d and .json | Notes |
{ "X3D": { "encoding":"UTF-8", "@profile":"Immersive", "@version":"3.3", "@xsd:noNamespaceSchemaLocation":"https://www.web3d.org/specifications/x3d-3.3.xsd", "JSON schema":"https://www.web3d.org/specifications/x3d-3.3-JSONSchema.json", "head": { "meta": [ { "@name":"title", "@content":"HelloWorld.x3d" }, { "@name":"description", "@content":"Simple X3D scene example: Hello World!" }, { "@name":"created", "@content":"30 October 2000" }, { "@name":"modified", "@content":"23 November 2014" }, { "@name":"creator", "@content":"Don Brutzman" }, { "@name":"Image", "@content":"HelloWorld.tall.png" }, { "@name":"reference", "@content":"http://en.wikipedia.org/wiki/Hello_world" }, { "@name":"reference", "@content":"en.wikipedia.org/wiki/Hello#\"Hello,_World\"_computer_program" }, { "@name":"reference", "@content":"http://en.wikibooks.org/w/index.php?title=Computer_Programming/Hello_world" }, { "@name":"reference", "@content":"http://www.HelloWorldExample.net" }, { "@name":"reference", "@content":"http://www.web3D.org" }, { "@name":"reference", "@content":"https://www.web3d.org/realtime-3d/news/internationalization-x3d" }, { "@name":"reference", "@content":"https://www.web3d.org/x3d/content/examples/HelloWorld.x3d" }, { "@name":"reference", "@content":"http://X3dGraphics.com/examples/X3dForAdvancedModeling/HelloWorldScenes" }, { "@name":"identifier", "@content":"http://X3dGraphics.com/examples/X3dForWebAuthors/Chapter01-TechnicalOverview/HelloWorld.x3d" }, { "@name":"license", "@content":"https://www.web3d.org/x3d/content/examples/license.html" }, { "@name":"generator", "@content":"X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit" }, { "@name":"reference", "@content":"HelloWorld.wrl" }, { "@name":"reference", "@content":"HelloWorld.x3dv" }, { "@name":"reference", "@content":"HelloWorld.x3db" }, { "@name":"reference", "@content":"HelloWorld.xhtml" }, { "@name":"reference", "@content":"HelloWorld.json" }, { "@name":"translated", "@content":"17 March 2016" }, { "@name":"generator", "@content":"X3dToJson.xslt, https://www.web3d.org/x3d/stylesheets/X3dToJson.html" }, { "@name":"warning", "@content":"An experimental version of X3D JSON encoding is used for this scene. Status online at https://www.web3d.org/wiki/index.php/X3D_JSON_Encoding" } ], "-children":[ { "#comment":"Alternate encodings: VRML97, X3D ClassicVRML Encoding, X3D Compressed Binary Encoding (CBE), X3DOM, JSON" } ] }, "Scene": { "-children":[ { "#comment":"Example scene to illustrate X3D nodes and fields (XML elements and attributes)" }, { "Group": { "-children":[ { "Viewpoint": { "@DEF":"ViewUpClose", "@centerOfRotation":[0,-1,0], "@description":"Hello world!", "@position":[0,-1,7] } }, { "Transform": { "@rotation":[0,1,0,3], "-children":[ { "Shape": { "-geometry": { "Sphere": { } }, "-appearance": { "Appearance": { "-material": { "Material": { "@DEF":"MaterialLightBlue", "@diffuseColor":[0.1,0.5,1] } }, "-texture": { "ImageTexture": { "@DEF":"ImageCloudlessEarth", "@url":[ "earth-topo.png","earth-topo.jpg","earth-topo-small.gif", "https://www.web3d.org/x3d/content/examples/Basic/earth-topo.png", "https://www.web3d.org/x3d/content/examples/Basic/earth-topo.jpg", "https://www.web3d.org/x3d/content/examples/Basic/earth-topo-small.gif"] } } } } } } ] } }, { "Transform": { "@translation":[0,-2,0], "-children":[ { "Shape": { "-geometry": { "Text": { "@DEF":"TextMessage", "@string":["Hello","world!"], "-fontStyle": { "FontStyle": { "@justify":["MIDDLE","MIDDLE"] } } } }, "-appearance": { "Appearance": { "-material": { "Material": { "@USE":"MaterialLightBlue" } } } } } } ] } } ] } } ] } } } |
Comments are treated as a unique-key array of objects, which appears before other child elements. Attributes with default values are omitted for clarity. Line breaks inserted in url arrays for readability. |
Source excerpts, .x3d and .json | Notes |
---|---|
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.3//EN" "https://www.web3d.org/specifications/x3d-3.3.dtd"> <X3D profile='Immersive' version='3.3' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.3.xsd'> <head> <component level='1' name='CADGeometry'/> <component level='1' name='HAnim'/> <unit category='length' conversionFactor='0.9144' name='Yards'/> <unit category='angle' conversionFactor='0.0174532925167' name='Degrees'/> <meta content='TestJsonEncoding.x3d' name='title'/> <meta content='Don Brutzman' name='creator'/> <meta content='29 March 2015' name='created'/> <meta content='3 November 2015' name='modified'/> <meta content='Test scene to ensure that X3dToJson xslt stylesheet translator properly converts X3D source into JavaScript Object Notation (JSON).' name='description'/> <meta content='TestJsonEncoding.json' name='reference'/> <meta content='https://www.web3d.org/wiki/index.php/X3D_JSON_Encoding' name='reference'/> <meta content='https://www.web3d.org/x3d/content/examples/Basic/development/TestJsonEncoding.x3d' name='identifier'/> <meta content='https://www.web3d.org/x3d/stylesheets/X3dToJson.xslt' name='reference'/> <meta content='https://www.web3d.org/x3d/stylesheets/X3dToJson.html' name='reference'/> <meta content='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit' name='generator'/> <meta content='../license.html' name='license'/> </head> <Scene> <!-- excerpted from HelloWorld.x3d --> <Group> <Viewpoint DEF='ViewUpClose' centerOfRotation='0 -1 0' description='Hello world!' position='0 -1 7'/> <Transform rotation='0 1 0 3'> <Shape> <Sphere/> <Appearance> <!-- Test leading zeroes inserted before (and trailing zeroes inserted after) decimal points: diffuseColor='.1 0.5 1.' --> <Material DEF='MaterialLightBlue' diffuseColor='.1 0.5 1.'/> <ImageTexture DEF='ImageCloudlessEarth' url='"earth-topo.png" "earth-topo.jpg" "earth-topo-small.gif" "https://www.web3d.org/x3d/content/examples/Basic/earth-topo.png" "https://www.web3d.org/x3d/content/examples/Basic/earth-topo.jpg" "https://www.web3d.org/x3d/content/examples/Basic/earth-topo-small.gif"'/> </Appearance> </Shape> </Transform> <Transform translation='-.1 -2 -.2'> <!-- Test leading zeroes inserted between -. values: translation='-.1 -2 -.2' --> <Shape> <Text DEF='TextMessage' string='"Hello" "JSON!"'> <FontStyle justify='"MIDDLE" "MIDDLE"'/> </Text> <Appearance> <Material USE='MaterialLightBlue'/> </Appearance> </Shape> </Transform> </Group> </Scene> </X3D> |
TestJsonEncoding.x3d
source, |
Source excerpts, .x3d and .json | Notes |
{ "X3D": { "encoding":"UTF-8", "@profile":"Immersive", "@version":"3.3", "@xsd:noNamespaceSchemaLocation":"https://www.web3d.org/specifications/x3d-3.3.xsd", "JSON schema":"https://www.web3d.org/specifications/x3d-3.3-JSONSchema.json", "head": { "component": [ { "@name":"CADGeometry", "@level":1 }, { "@name":"HAnim", "@level":1 } ], "unit": [ { "@name":"Yards", "@category":"length", "@conversionFactor":0.9144 }, { "@name":"Degrees", "@category":"angle", "@conversionFactor":0.0174532925167 } ], "meta": [ { "@name":"title", "@content":"TestJsonEncoding.x3d" }, { "@name":"creator", "@content":"Don Brutzman" }, { "@name":"created", "@content":"29 March 2015" }, { "@name":"modified", "@content":"3 November 2015" }, { "@name":"description", "@content":"Test scene to ensure that X3dToJson xslt stylesheet translator properly converts X3D source into JavaScript Object Notation (JSON)." }, { "@name":"reference", "@content":"TestJsonEncoding.json" }, { "@name":"reference", "@content":"https://www.web3d.org/wiki/index.php/X3D_JSON_Encoding" }, { "@name":"identifier", "@content":"https://www.web3d.org/x3d/content/examples/Basic/development/TestJsonEncoding.x3d" }, { "@name":"reference", "@content":"https://www.web3d.org/x3d/stylesheets/X3dToJson.xslt" }, { "@name":"reference", "@content":"https://www.web3d.org/x3d/stylesheets/X3dToJson.html" }, { "@name":"generator", "@content":"X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit" }, { "@name":"license", "@content":"../license.html" }, { "@name":"translated", "@content":"17 March 2016" }, { "@name":"generator", "@content":"X3dToJson.xslt, https://www.web3d.org/x3d/stylesheets/X3dToJson.html" }, { "@name":"warning", "@content":"An experimental version of X3D JSON encoding is used for this scene. Status online at https://www.web3d.org/wiki/index.php/X3D_JSON_Encoding" } ] }, "Scene": { "-children":[ { "#comment":"excerpted from HelloWorld.x3d" }, { "Group": { "-children":[ { "Viewpoint": { "@DEF":"ViewUpClose", "@centerOfRotation":[0,-1,0], "@description":"Hello world!", "@position":[0,-1,7] } }, { "Transform": { "@rotation":[0,1,0,3], "-children":[ { "Shape": { "-geometry": { "Sphere": { } }, "-appearance": { "Appearance": { "-children":[ { "#comment":"Test leading zeroes inserted before (and trailing zeroes inserted after) decimal points: diffuseColor='.1 0.5 1.'" } ], "-material": { "Material": { "@DEF":"MaterialLightBlue", "@diffuseColor":[0.1,0.5,1.0] } }, "-texture": { "ImageTexture": { "@DEF":"ImageCloudlessEarth", "@url":[ "earth-topo.png","earth-topo.jpg","earth-topo-small.gif", "https://www.web3d.org/x3d/content/examples/Basic/earth-topo.png", "https://www.web3d.org/x3d/content/examples/Basic/earth-topo.jpg", "https://www.web3d.org/x3d/content/examples/Basic/earth-topo-small.gif"] } } } } } } ] } }, { "Transform": { "@translation":[-0.1,-2,-0.2], "-children":[ { "#comment":"Test leading zeroes inserted between -. values: translation='-.1 -2 -.2'" }, { "Shape": { "-geometry": { "Text": { "@DEF":"TextMessage", "@string":["Hello","JSON!"], "-fontStyle": { "FontStyle": { "@justify":["MIDDLE","MIDDLE"] } } } }, "-appearance": { "Appearance": { "-material": { "Material": { "@USE":"MaterialLightBlue" } } } } } } ] } } ] } } ] } } } |
Comments are treated as a unique-key array of objects, which appears before other child elements. Attributes with default values are omitted for clarity. Line breaks inserted in url arrays for readability. |
Source excerpts, .x3d and .json | Notes |
---|---|
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE X3D PUBLIC "ISO//Web3D//DTD X3D 3.3//EN" "https://www.web3d.org/specifications/x3d-3.3.dtd"> <X3D profile='Interactive' version='3.3' xmlns:xsd='http://www.w3.org/2001/XMLSchema-instance' xsd:noNamespaceSchemaLocation='https://www.web3d.org/specifications/x3d-3.3.xsd'> <head> <meta content='OrigamiCranes.x3d' name='title'/> <meta content='Origami Cranes with black/white contrast as art work for Black Swan game.' name='description'/> <meta content='2 November 2014' name='created'/> <meta content='3 November 2015' name='modified'/> <meta content='epicpopcorn' name='creator'/> <meta content='http://www.turbosquid.com/FullPreview/Index.cfm/ID/598176' name='reference'/> <meta content='crane.obj' name='reference'/> <meta content='OrigamiCrane.ply' name='reference'/> <meta content='Don Brutzman' name='translator'/> <meta content='http://en.wikipedia.org/wiki/Swan' name='reference'/> <meta content='http://en.wikipedia.org/wiki/Orizuru' name='reference'/> <meta content='http://www.youtube.com/watch?v=CXwwPgMiEPc' name='reference'/> <meta content='http://www.origami-make.com/howto-origami-swan.php' name='reference'/> <meta content='http://origami.about.com/od/Origami-Animals/tp/How-To-Make-An-Origami-Swan.htm' name='reference'/> <meta content='http://en.wikipedia.org/wiki/The_Black_Swan_(2007_book)' name='reference'/> <meta content='http://en.wikipedia.org/wiki/Nassim_Nicholas_Taleb' name='reference'/> <meta content='Making sense of The Black Swan por Mark Crovelli, quarta-feira, 18 de abril de 2012' name='reference'/> <meta content='http://www.mises.org.br/Article.aspx?id=1284' name='reference'/> <meta content='http://www.mises.org.br/images/articles/2012/Abril/black_swan.jpg' name='Image'/> <meta content='OrigamiBlackSwanWhiteSwan.jpg' name='Image'/> <meta content='http://x3dGraphics.com/examples/X3dForAdvancedModeling/Animation/OrigamiCranes.x3d' name='identifier'/> <meta content='OrigamiCraneMeshlab.png' name='Image'/> <meta content='Meshlab X3D Exported, http://meshlab.sourceforge.net' name='generator'/> <meta content='X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit' name='generator'/> <meta content='http://support.turbosquid.com/entries/31030006-Royalty-Free-License?locale=1' name='license'/> <meta content='../license.html' name='license'/> </head> <Scene> <Background groundAngle='1.5707' groundColor='1 1 1 1 1 1' skyAngle='0' skyColor='0 0 0 0 0 0'/> <NavigationInfo type='"NONE"'/> <PointLight intensity='0.3' location='0 2 6'/> <PointLight intensity='0.3' location='0 -2 6'/> <Group DEF='AnimatedView'> <Viewpoint DEF='MovingPov' description='Rotating Viewpoint'/> <TimeSensor DEF='PovClock' cycleInterval='60' loop='true'/> <PositionInterpolator DEF='MovingPovLocation' key='0 0.125 0.25 0.375 0.5 0.625 0.75 0.875 1' keyValue='0 0 3 3 0 2 3 0 2 0 0 3 0 0 3 -3 0 2 -3 0 2 0 0 3 0 0 3'/> <ROUTE fromField='fraction_changed' fromNode='PovClock' toField='set_fraction' toNode='MovingPovLocation'/> <ROUTE fromField='value_changed' fromNode='MovingPovLocation' toField='position' toNode='MovingPov'/> <OrientationInterpolator DEF='MovingPovRotation' key='0 0.125 0.25 0.375 0.5 0.625 0.75 0.875 1' keyValue='0 1 0 0 0 1 0 0.982794 0 1 0 0.982794 0 1 0 0 0 1 0 0 0 1 0 -0.982794 0 1 0 -0.982794 0 1 0 0 0 1 0 0'/> <ROUTE fromField='fraction_changed' fromNode='PovClock' toField='set_fraction' toNode='MovingPovRotation'/> <ROUTE fromField='value_changed' fromNode='MovingPovRotation' toField='set_orientation' toNode='MovingPov'/> </Group> <Viewpoint description='Origami Cranes, from ahead' orientation='0 1 0 0.982794' position='3 0 2'/> <Viewpoint description='Origami Cranes, mirror image' position='0 0 3'/> <Viewpoint description='Origami Cranes, from behind' orientation='0 1 0 -0.982794' position='-3 0 2'/> <Transform DEF='CraneAbove' rotation='0 1 0 1.745329'> <!-- Rotation was necessary to point along X axis --> <Transform DEF='TranslateToOrigin' translation='0.25 -0.18 -0.1'> <Shape DEF='CraneShapeWhite'> <IndexedFaceSet DEF='CraneIFS' coordIndex='0 1 2 -1 0 2 3 -1 4 5 2 -1 [... omitted ...]' solid='false'> <!-- Original model values are quite large, converted from inches to meters using factor 0.0254 to rescale, wingtip is now 0.8m and length is 1.5m. --> <Coordinate point='-0.39882 0.8134 0.63626 -0.33169 0.81323 0.53558 [... omitted ...]'/> </IndexedFaceSet> <Appearance> <Material diffuseColor='0.9 0.9 0.9'/> </Appearance> </Shape> </Transform> </Transform> <Transform DEF='CraneBelow' rotation='1 0 0 3.141593'> <Transform rotation='0 1 0 1.745329'> <Transform translation='0.25 -0.18 -0.1'> <Shape DEF='CraneShapeBlack'> <IndexedFaceSet USE='CraneIFS'/> <Appearance> <Material diffuseColor='0.15 0.15 0.15'/> </Appearance> </Shape> </Transform> </Transform> </Transform> </Scene> </X3D> |
OrigamiCranes.x3d
source, |
Source excerpts, .x3d and .json | Notes |
{ "X3D": { "encoding":"UTF-8", "@profile":"Interactive", "@version":"3.3", "@xsd:noNamespaceSchemaLocation":"https://www.web3d.org/specifications/x3d-3.3.xsd", "JSON schema":"https://www.web3d.org/specifications/x3d-3.3-JSONSchema.json", "head": { "meta": [ { "@name":"title", "@content":"OrigamiCranes.x3d" }, { "@name":"description", "@content":"Origami Cranes with black/white contrast as art work for Black Swan game." }, { "@name":"created", "@content":"2 November 2014" }, { "@name":"modified", "@content":"11 November 2015" }, { "@name":"creator", "@content":"epicpopcorn" }, { "@name":"reference", "@content":"http://www.turbosquid.com/FullPreview/Index.cfm/ID/598176" }, { "@name":"reference", "@content":"crane.obj" }, { "@name":"reference", "@content":"OrigamiCrane.ply" }, { "@name":"translator", "@content":"Don Brutzman" }, { "@name":"reference", "@content":"http://en.wikipedia.org/wiki/Swan" }, { "@name":"reference", "@content":"http://en.wikipedia.org/wiki/Orizuru" }, { "@name":"reference", "@content":"http://www.youtube.com/watch?v=CXwwPgMiEPc" }, { "@name":"reference", "@content":"http://www.origami-make.com/howto-origami-swan.php" }, { "@name":"reference", "@content":"http://origami.about.com/od/Origami-Animals/tp/How-To-Make-An-Origami-Swan.htm" }, { "@name":"reference", "@content":"http://en.wikipedia.org/wiki/The_Black_Swan_(2007_book)" }, { "@name":"reference", "@content":"http://en.wikipedia.org/wiki/Nassim_Nicholas_Taleb" }, { "@name":"reference", "@content":"Making sense of The Black Swan por Mark Crovelli, quarta-feira, 18 de abril de 2012" }, { "@name":"reference", "@content":"http://www.mises.org.br/Article.aspx?id=1284" }, { "@name":"Image", "@content":"http://www.mises.org.br/images/articles/2012/Abril/black_swan.jpg" }, { "@name":"Image", "@content":"OrigamiBlackSwanWhiteSwan.jpg" }, { "@name":"identifier", "@content":"http://x3dGraphics.com/examples/X3dForAdvancedModeling/Animation/OrigamiCranes.x3d" }, { "@name":"Image", "@content":"OrigamiCraneMeshlab.png" }, { "@name":"generator", "@content":"Meshlab X3D Exported, http://meshlab.sourceforge.net" }, { "@name":"generator", "@content":"X3D-Edit 3.3, https://savage.nps.edu/X3D-Edit" }, { "@name":"license", "@content":"http://support.turbosquid.com/entries/31030006-Royalty-Free-License?locale=1" }, { "@name":"license", "@content":"../license.html" }, { "@name":"translated", "@content":"17 March 2016" }, { "@name":"generator", "@content":"X3dToJson.xslt, https://www.web3d.org/x3d/stylesheets/X3dToJson.html" }, { "@name":"warning", "@content":"An experimental version of X3D JSON encoding is used for this scene Status online at https://www.web3d.org/wiki/index.php/X3D_JSON_Encoding" } ] }, "Scene": { "-children":[ { "Background": { "@groundAngle":[1.5707], "@groundColor":[1,1,1,1,1,1], "@skyAngle":[0], "@skyColor":[0,0,0,0,0,0] } }, { "NavigationInfo": { "@type":["NONE"] } }, { "PointLight": { "@intensity":0.3, "@location":[0,2,6] } }, { "PointLight": { "@intensity":0.3, "@location":[0,-2,6] } }, { "Group": { "@DEF":"AnimatedView", "-children":[ { "Viewpoint": { "@DEF":"MovingPov", "@description":"Rotating Viewpoint" } }, { "TimeSensor": { "@DEF":"PovClock", "@cycleInterval":60, "@loop":true } }, { "PositionInterpolator": { "@DEF":"MovingPovLocation", "@key":[0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1], "@keyValue":[0,0,3,3,0,2,3,0,2,0,0,3,0,0,3,-3,0,2,-3,0,2,0,0,3,0,0,3] } }, { "ROUTE": { "@fromField":"fraction_changed", "@fromNode":"PovClock", "@toField":"set_fraction", "@toNode":"MovingPovLocation" } }, { "ROUTE": { "@fromField":"value_changed", "@fromNode":"MovingPovLocation", "@toField":"position", "@toNode":"MovingPov" } }, { "OrientationInterpolator": { "@DEF":"MovingPovRotation", "@key":[0,0.125,0.25,0.375,0.5,0.625,0.75,0.875,1], "@keyValue":[0,1,0,0,0,1,0,0.982794,0,1,0,0.982794,0,1,0,0,0,1,0,0, 0,1,0,-0.982794,0,1,0,-0.982794,0,1,0,0,0,1,0,0] } }, { "ROUTE": { "@fromField":"fraction_changed", "@fromNode":"PovClock", "@toField":"set_fraction", "@toNode":"MovingPovRotation" } }, { "ROUTE": { "@fromField":"value_changed", "@fromNode":"MovingPovRotation", "@toField":"set_orientation", "@toNode":"MovingPov" } } ] } }, { "Viewpoint": { "@description":"Origami Cranes, from ahead", "@orientation":[0,1,0,0.982794], "@position":[3,0,2] } }, { "Viewpoint": { "@description":"Origami Cranes, mirror image", "@position":[0,0,3] } }, { "Viewpoint": { "@description":"Origami Cranes, from behind", "@orientation":[0,1,0,-0.982794], "@position":[-3,0,2] } }, { "Transform": { "@DEF":"CraneAbove", "@rotation":[0,1,0,1.745329], "-children":[ { "#comment":"Rotation was necessary to point along X axis" }, { "Transform": { "@DEF":"TranslateToOrigin", "@translation":[0.25,-0.18,-0.1], "-children":[ { "Shape": { "@DEF":"CraneShapeWhite", "-geometry": { "IndexedFaceSet": { "@DEF":"CraneIFS", "@coordIndex":[0,1,2,-1,0,2,3,-1,4,5,2,-1,4,2,1,-1, 1,0,6,-1,7,2,8,-1,3,9,10,-1,11,12,13,-1,12,9,14,-1, 11,9,12,-1,15,2,7,-1,14,9,2,-1,7,10,15,-1,12,15,16,-1, 13,12,16,-1,14,15,12,-1,16,17,13,-1,13,17,11,-1, 15,14,2,-1,9,3,2,-1,1,6,4,-1,18,8,2,-1,5,19,20,-1, 21,22,23,-1,23,24,20,-1,21,23,20,-1,25,18,2,-1, 24,2,20,-1,18,25,19,-1,23,26,25,-1,22,26,23,-1, 24,23,25,-1,26,22,27,-1,22,21,27,-1,25,2,24,-1,20,2,5,-1], "@solid":false, "-children":[ { "#comment":"Original model values are quite large, converted from inches to meters using factor 0.0254 to rescale, wingtip is now 0.8m and length is 1.5m." } ], "-coord": { "Coordinate": { "@point":[-0.39882,0.8134,0.63626, -0.33169,0.81323,0.53558,-0.2503,0.31524, 0.08395,-0.35153,0.19681,0.28621,-0.30394, 0.8134,0.65336,-0.22605,0.19681,0.30883, -0.37413,0.67816,0.77105,-0.28707,0.18877, -0.12428,-0.11107,0.78537,-0.68858,-0.40796, 0.34843,0.27538,-0.37208,0.32894,0.06357, -0.45279,0.43502,0.29314,-0.37197,0.32891, 0.06359,-0.40743,0.43285,0.05396,-0.25021, 0.52642,0.08345,-0.33581,0.34187,-0.15904, -0.36691,0.43174,-0.18336,-1.12733,0.86101, -0.07052,-0.14315,0.18877,-0.09835,-0.12906, 0.32894,0.10737,-0.16939,0.34843,0.31838, -0.13358,0.43502,0.35067,-0.09258,0.43285, 0.11071,-0.12918,0.32891,0.10735,-0.25021, 0.52642,0.08345,-0.08534,0.34187,-0.1139, -0.0477,0.43174,-0.12584,0.62547,0.86101,0.24538] } } } }, "-appearance": { "Appearance": { "-material": { "Material": { "@diffuseColor":[0.9,0.9,0.9] } } } } } } ] } } ] } }, { "Transform": { "@DEF":"CraneBelow", "@rotation":[1,0,0,3.141593], "-children":[ { "Transform": { "@rotation":[0,1,0,1.745329], "-children":[ { "Transform": { "@translation":[0.25,-0.18,-0.1], "-children":[ { "Shape": { "@DEF":"CraneShapeBlack", "-geometry": { "IndexedFaceSet": { "@USE":"CraneIFS" } }, "-appearance": { "Appearance": { "-material": { "Material": { "@diffuseColor":[0.15,0.15,0.15] } } } } } } ] } } ] } } ] } } ] } } } |
Comments are treated as a unique-key array of objects, which appears before other child elements. Note that the two ROUTE pairs which were not adjacent in the XML encoding are now collected together. Attributes with default values are omitted for clarity. |
A variety of design issues continue to get investigated and addressed. Most items are now complete.
As design patterns stabilize, X3D JSON loading and round-trip testing (.x3d <==> .json
) are
confirming that the right design correspondences have been implemented.
The current stylesheet implementation handles the majority of conversion issues, including the following.
"keyValue": [0,0,0,1,1,1,2,2,2],
"keyValue": [ [0,0,0],[1,1,1],[2,2,2] ],
\"
.
X3D
element, or perhaps begin with the Scene
element.
#comment
string array.
Partial re-ordering may occur when multiple sibling comments are moved to appear prior to peer nodes.
#sourceCode
string array.
-children
field.
This simplifies loading and maintains symmetry with XML encoding, which is important for serialization.
#comment
and ROUTE
is similar to other -children
nodes,
regardless of whether the parent X3D node allows other children nodes.
-children
key.
-children
key.
null
is appropriate.
JSON.minify()
to strip comments.
{ "X3D" {
identifies the beginning of an X3D JSON object,
with no #comment
entries allowed externally.
Leaving the output JSON as simple as possible avoids code problems and
provides programmers with the greatest possible flexibility. Further
practice and analysis will show if a JSON header is needed; probably a non-problem.
Stylesheet options and default values:
<xsl:param name="stripComments"><xsl:text>false</xsl:text></xsl:param> <xsl:param name="stripDefaultAttributes"><xsl:text>true</xsl:text></xsl:param> <xsl:param name="indentEnabled"><xsl:text>true</xsl:text></xsl:param> <xsl:param name="sourceCode"><xsl:text>strings</xsl:text></xsl:param> <!-- escaped | strings | plaintext --> <xsl:param name="traceEnabled"><xsl:text>false</xsl:text></xsl:param> <xsl:param name="traceScripts"><xsl:text>false</xsl:text></xsl:param>
The sourceCode options govern the output mode of #sourceCode
code embedded in
Script,
ShaderPart
and
ShaderProgram
nodes.
\n
character, thus a single line results
Note that converted JavaScript source can be broken if it contains // comment characters
since any subsequent source code is effectively ignored if stuffed into a single line.
Note that X3D-Edit has an X3D Conversions: X3D to JSON panel that offers configuration of several options for testing.
XSLT stylesheets are reusable and can be invoked by a wide variety of tools and programming languages.
Essential references
Additional references
John Carlson has provided numerous insights and made many contributions during this group effort. He reports:
I have created a JSON loader for X3DOM that load JSON across the WWW.
https://github.com/coderextreme/X3DJSONLD (including a Pseudocode description).
Warning: under active development! This has been tested on a number of scenes in the Web3D Examples archives. Particular caution: a number of objects are still in the global scope of JavaScript.
Suggestions and contributions are welcome. As usual, forks of the repository and pull requests for potential changes are welcome if authors agree to the license.
Now available: the X3D JSON Loader has a README and Getting Started guide for this Application Programming Interface (API). Excerpts follow.
Introducing: the X3D JSON Loader (1.0 beta) and X3D JSON Prototype Expander (1.0 alpha)
For web browser testing, a live development version of the X3D JSON loader is recommended by downloading locally or forking.
To use the JSON loader in your HTML, put:
<script type="text/javascript" src="https://raw.githubusercontent.com/coderextreme/X3DJSONLD/master/X3DJSONLD.js"></script>Then somewhere in the script afterwards (see index.html for example usage) call
loadX3DJS(selector, json, url, xml);where
selector
is the CSS selector which you want to append the X3DOM HTML code to.json
is the X3D JSON you want to display.url
is used for resolving URLs in the X3D JSON. Should be similar or the same as the URL you passed to retrieve the JSON from the server.xml
is the XML for inclusion into Cobweb.Use
xml.join("")
when passing thexml
object tocreateX3DFromString()
Sample code for putting Cobweb into an
iframe
with idcobwebframe
(thank you Andreas Plesch):var content = xml.join(""); var cobwebWindow = document.getElementById("cobwebframe").contentWindow ; var cobwebEle = cobwebWindow.document.getElementById("x3dele"); if (typeof cobwebWindow.X3D !== 'undefined') { var browser = cobwebWindow.X3D.getBrowser(cobwebEle); browser.replaceWorld(browser.createX3DFromString(content)); // etc. }For the prototype expander, again use a live, development version (local copy recommended). (Modification ofExternProtoDeclare statements is not supported yet.) Invocation:
<script type="text/javascript" src="https://raw.githubusercontent.com/coderextreme/X3DJSONLD/master/PrototypeExpander.js"></script> prototypeExpander(json, scope);where
json
is the X3DJSON you want to expand photos for (also modifies the parameter as output).scope
is a scope string added to DEF name and id attributes for ROUTE fromNode and toNode attributes. The empty string "" is fine for a top-level call.There is useful code you may want to look at in index.html with long form at X3DExamplesViewer.html. These pages work when the X3D Examples are installed locally.
Community-visible efforts continue to test this library in tandem with the X3dToJson outputs. Usage reports are helpful and influential, future automation of verification is also likely.
When we get the X3D JSON encoding fully stable (it is close now), future work is also under consideration. John again reports:
I have investigated auto-generating a good portion of the JSON schema to avoid a lot of work. This will not replace eventual human intervention on editing a JSON schema, but is provided to bootstrap schema efforts. This uses Jsonix. Generating data structure code from XSD using JAXB (or other) and then taking data structure and converting it to JSON schema using Jackson (or other) should be considered as an alternative. Jsonix does not provide for a good X3D JSON standard as there is a lot of differences in the mappings and in the schema each time is is run. There are ways to support patterns in JAXB (JSR-303), which doesn�t come by default with Jsonix yet. I am not sure how to implement patterns in JSON schema. This may depend on the difference between JSON regexes and XSD regexes.
It is hoped that the X3D JSON standard will inform itself of the JSON schema standard, and will not deviate too far from existing tools in hopes of easing the burden of creating a JSON schema. We should investigate Ajv and other JSON validators once we have a JSON schema.
Additional contributions:
node.js
console directions
that shows file loading plus JavaScript object references to X3D JSON data structures.
JavaScript libraries of related interest as potential users of X3D JSON:
Specialized tools are in development to provide support for X3D JSON.
Many tools are available for JSON.
eval()
.
Discussions regarding X3D JSON Encoding design and usage occur on the x3d-public@web3d.org mailing list (subscribe).
Questions, suggestions, additions and comments about this X3D to JSON Stylesheet Converter page are welcome. Please send them to Don Brutzman (brutzman at nps.edu).
Master version of this X3D to JSON Stylesheet Converter description page is available at
https://www.web3d.org/x3d/stylesheets/X3dToJson.html
Master version of this X3D to JSON Stylesheet Converter itself is available at
https://www.web3d.org/x3d/stylesheets/X3dToJson.xslt
and in version control at
https://sourceforge.net/p/x3d/code/HEAD/tree/www.web3d.org/x3d/stylesheets/X3dToJson.xslt
Updated: 5 July 2022