Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing support for array conversion #181

Closed
hazaart opened this issue Aug 14, 2019 · 18 comments
Closed

Missing support for array conversion #181

hazaart opened this issue Aug 14, 2019 · 18 comments

Comments

@hazaart
Copy link

hazaart commented Aug 14, 2019

In case a node exists multiple time in the same parent, it will automatically be converted to a JS array.
If the node occurs only once however in the dataset (eventhough it could occur multiple times in theory), the conversion will create an object cause it has no way of knowing it should convert it to an array.
Other libraries have support for this by adding an array in the parsing options containing a list of elements that always need to be converted to an array.
Example https://github.com/abdolence/x2js has support via 'arrayAccessFormPaths'.

I am surprised this basic conceptual issue in xml to json conversion is not yet covered by this widely used library. Makes for a lot of painful checks on the output.

@amitguptagwl
Copy link
Member

I am surprised this basic conceptual issue in xml to json conversion is not yet covered by this widely used library. Makes for a lot of painful checks on the output.

😄 Have you checked for the already raised issues and the discussion on the same topic?

Please give us an example so we can understand if your rasied concern is different.

@hazaart
Copy link
Author

hazaart commented Aug 19, 2019

Hi,

It is the same as issue #166
But it should be supported in the library.
If you allow to pass an optional array which specifies which nodenames should always convert to Array.
See example implementation as mentioned above in x2js.

Being a conceptual issue when making a conversion from XML to JSON, I think it would be nice if a solution is supported by the library.

Thanks

@amitguptagwl
Copy link
Member

There is no standard for XML to JSON/JS Object conversion. Hence, we need to finalize the response which suits to our implementation and users expectation. People feel its need but no one yet given us the clear requirement.

We don't want hurry. Because many changes cant be reverted once the users at world level start using them.

@amitguptagwl
Copy link
Member

I'm closing this issue as it is duplicate for the other issue. If you'll feel we should keep it open, please reopen

@hazaart
Copy link
Author

hazaart commented Aug 19, 2019

"People feel its need but no one yet given us the clear requirement."
How do you mean, I just did :-)

In the options we can pass for parsing, add a new optional array. This way there is no conflict with the existing way of working.

arrayAccessFormPaths : [] - Array access paths - use this option to configure paths to XML elements always in "array form". You can configure beforehand paths to all your array elements based on XSD or your knowledge. Every path could be a simple string (like 'parent.child1.child2'), a regex (like /.*.child2/), or a custom function. Default is empty

@amitguptagwl
Copy link
Member

This is not a clear requirement. I doubt if you have seen the previous discussions.

@DazChong
Copy link

Yes, this is a missing feature.
Imaging scenario of user object with multiple emails as array, some user have multiple emails and some only have 1.

@amitguptagwl
Copy link
Member

@hazaart @DazChong FYR #135

@Kaarel
Copy link

Kaarel commented Sep 11, 2019

Use cases:
Invoices, stock inventory, accounting, shopping carts, travel reservations, players in a game etc etc. They all have 0 to n items, in practice 1 to n. Basically almost every use case :) 1 is just a special case of n element array.

We have a lot of use cases like below. We do not control the XML that is sent to us, we just need to work with it.

<report>
    <store>
        <region>US</region>
        <inventory>
            <item>
                <name>Banana</name>
                <count>200</count>
            </item>
            <item>
                <name>Apple</name>
                <count>100</count>
            </item>
        </inventory>
    </store>
    <store>
        <region>EU</region>
        <inventory>
            <item>
                <name>Banana</name>
                <count>100</count>
            </item>
        </inventory>
    </store>
</report>

which fast-xml-parser parses into

{
  "report": {
    "store": [
      {
        "region": "US",
        "inventory": {
          "item": [
            {
              "name": "Banana",
              "count": "200"
            },
            {
              "name": "Apple",
              "count": "100"
            }
          ]
        }
      },
      {
        "region": "EU",
        "inventory": {
          "item": {
            "name": "Banana",
            "count": "100"
          }
        }
      }
    ]
  }
}

Note that the type of store.inventory.item changes! Without this feature accessing inventory items for every store requires always testing if store.inventory.item is array or not. Same for iterating over stores as well, as the report could contain just one store. In practice there are a lot more elements like that in the XML we parse. This results in an unnecessarily complicated application code.

Basically this is the reason we can not use fast-xml-parser.

@amitguptagwl
Copy link
Member

Thanks for highlighting this @Kaarel . So if let's suppose, we have some option which basically renders a nested tag always an array, it'll look like as follow;

{
    "report": [
        {
            "store": [
                {
                    "region": "US",
                    "inventory": [
                        {
                            "item": [
                                {
                                    "name": "Banana",
                                    "count": "200"
                                },
                                {
                                    "name": "Apple",
                                    "count": "100"
                                }
                            ]
                        }
                    ]
                },
                {
                    "region": "EU",
                    "inventory": [
                        {
                            "item": [
                                {
                                    "name": "Banana",
                                    "count": "100"
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}

will it solve the purpose?

@amitguptagwl
Copy link
Member

I have started the discussion here;

#190

@Kaarel
Copy link

Kaarel commented Oct 2, 2019

Yes, specifically the strict mode in the examples of #190

@gknapp
Copy link

gknapp commented Oct 21, 2019

I'm using openlayers, it expects single values be a collection (array) and not unwrapped (object). It checks the parent node length but fails when the single value is unwrapped. Having a configuration option for this would mean I could use fast-xml-parser.

@amitguptagwl
Copy link
Member

@gknapp Have u looked at #190 ? does it solve ur purpose? if not please give an example of your expectation.

@gknapp
Copy link

gknapp commented Oct 24, 2019

@amitguptagwl Yes that's exactly what's needed. I knew it was coming but didn't think it was available on npm yet?

@amitguptagwl
Copy link
Member

It is available on Github. I'll publish that on Github tomorrow or on weekend.

@hazaart
Copy link
Author

hazaart commented Oct 24, 2019

I don't think it is wishfull that every single node is transformed into an array. We should be able to control which node names have to always convert to array.

You may have levels in the XML that will only occur once. Take the tag for example in the above XML.
Let's say you wish to repeat over the stores you need to access it via report[0].stores. Having to add the index to the report makes for unreadable code and it becomes difficult to see which nodes can in reality recur and which ones don't.

A desired solution would be that the user can pass in an array of nodenames which should always be transformed to array.

Example:

const jsObj = parser.parse(xmlData, {
      arrayNodes: ["store", "item"]
});

@amitguptagwl
Copy link
Member

I'm not sure how many users wish to use arrayMode in this way, but this can be added in a future version if more users feel its need.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants