Skip to content

Unnecessary addition of "rest" property breaking marshaling #75

Closed
@mike-marcacci

Description

@mike-marcacci

Hi there, this may be related to #69 and highsource/jsonix#149, but has a slightly different manifestation.

Essentially, a sequence embedded in a choice that is not the only part of a parent sequence somehow causes the child's elements to be mapped to a nonexistant rest property. Unmarshalling works as expected, even with the strange mapping; but when trying to marshal the unmarshalled value back to XML (or when trying to marshal any expected data structure), the relevant properties are stripped.

Here's a simplified XSD that illustrates this case, but the real ones that show this problem live here.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="testxsd" xmlns:xp="testxsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">

    <xs:simpleType name="string25Type">
        <xs:restriction base="xs:string">
            <xs:maxLength value="25" />
        </xs:restriction>
    </xs:simpleType>

    <xs:complexType name="extensionType">
        <xs:attribute name="extId" type="xp:string25Type"/>
    </xs:complexType>

    <xs:element name="exampleElement">
        <xs:complexType>
            <xs:complexContent>
                <xs:extension base="xp:extensionType">
                    <xs:sequence>
                        <xs:choice>
                            <xs:sequence>
                                <xs:element name="exampleId" type="xp:string25Type"/>
                                <xs:element name="constant" type="xp:string25Type" minOccurs="0"/>
                            </xs:sequence>
                            <xs:sequence>
                                <xs:element name="exampleName" type="xp:string25Type"/>
                                <xs:element name="constant" type="xp:string25Type" minOccurs="0"/>
                            </xs:sequence>
                        </xs:choice>
                        <xs:element name="aaa" type="xp:string25Type"/>
                        <xs:element name="bbb" type="xp:string25Type" minOccurs="0"/>
                    </xs:sequence>
                </xs:extension>
            </xs:complexContent>
        </xs:complexType>
    </xs:element>
</xs:schema>

This generates the following mapping; notice the surprise name: 'rest' piece:

{
  name: 'testxsd',
  defaultElementNamespaceURI: 'testxsd',
  typeInfos: [
    {
      localName: 'ExampleElement',
      typeName: null,
      baseTypeInfo: '.ExtensionType',
      propertyInfos: [
        {
          name: 'rest',
          required: true,
          minOccurs: 2,
          maxOccurs: 4,
          collection: true,
          mixed: false,
          allowDom: false,
          elementTypeInfos: [
            { elementName: 'aaa' },
            { elementName: 'exampleId' },
            { elementName: 'bbb' },
            { elementName: 'constant' },
            { elementName: 'exampleName' }
          ],
          type: 'elementRefs'
        }
      ]
    },
    {
      localName: 'ExtensionType',
      typeName: 'extensionType',
      propertyInfos: [
        {
          name: 'extId',
          attributeName:
          {
            localPart: 'extId'
          },
          type: 'attribute'
        }
      ]
    }
  ],
  elementInfos: [
    {
      elementName: 'exampleName',
      scope: '.ExampleElement'
    },
    {
      elementName: 'bbb',
      scope: '.ExampleElement'
    },
    {
      elementName: 'exampleId',
      scope: '.ExampleElement'
    },
    {
      elementName: 'constant',
      scope: '.ExampleElement'
    },
    {
      elementName: 'aaa',
      scope: '.ExampleElement'
    },
    {
      typeInfo: '.ExampleElement',
      elementName: 'exampleElement'
    }
  ]
}

When using this mapping, I get the following results:

var Jsonix = require('jsonix').Jsonix;
var mapping = require('./testxsd.js').testxsd;
var context = new Jsonix.Context([mapping], {
	mappingStyle: 'simplified',
	namespacePrefixes: {
		'testxsd': ''
	}
});

var marshaller = context.createMarshaller();
var unmarshaller = context.createUnmarshaller();


// this is how the marshaller SHOULD work:
console.log(marshaller.marshalString({
	name: {
		namespaceURI: 'testxsd',
		localPart: 'exampleElement'
	},
	value: {
		extId: '111',
		exampleId: '12345',
		aaa: 'some value'
	}
}));

// =>
// <exampleElement xmlns="testxsd" extId="111"/>




// this is how the marshaller "works":
console.log(marshaller.marshalString({
	name: {
		namespaceURI: 'testxsd',
		localPart: 'exampleElement'
	},
	value: {
		extId: '111',
		rest: [
			{exampleId: '12345'},
			{aaa: 'some value'}
		]
	}
}));


// =>
// <exampleElement xmlns="testxsd" extId="111"><exampleId>12345</exampleId><aaa>some value</aaa></exampleElement>




// the unmarshaller works fine:
console.log(JSON.stringify(unmarshaller.unmarshalString(`
	<exampleElement xmlns="testxsd" extId="111">
		<exampleId>12345</exampleId>
		<aaa>some value</aaa>
	</exampleElement>
`)));


// =>
// {"exampleElement":{"TYPE_NAME":"testxsd.ExampleElement","extId":"111","rest":[{"exampleId":"12345"},{"aaa":"some value"}]}}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions