kgiszczak / shale

Shale is a Ruby object mapper and serializer for JSON, YAML, TOML, CSV and XML. It allows you to parse JSON, YAML, TOML, CSV and XML data and convert it into Ruby data structures, as well as serialize data structures into JSON, YAML, TOML, CSV or XML.
https://shalerb.org/
MIT License
618 stars 19 forks source link

Are union types supported? #6

Closed billy1kaplan closed 1 year ago

billy1kaplan commented 1 year ago

Thanks for your hard work on this, this looks awesome!

I was curious of union types are supported (e.g. anyOf in JSON Schema or xsd:choice in XSD).

kgiszczak commented 1 year ago

Hey, sorry for such a delay. They are supported when you generate models from the schema e.g.

json = <<~DATA
{
  "type": "object",
  "properties": {
    "firstName": {
      "anyOf": [
        { "type": "string" },
        { "type": "number" }
      ]
    },
    "lastName": {
      "type": "string"
    }
  }
}
DATA

puts Shale::Schema.from_json([json]).values[0]

firstName attribute will have a type of Shale::Type::Value meaning it will accept anything and won't type cast:

require 'shale'

class Root < Shale::Mapper
  attribute :first_name, Shale::Type::Value
  attribute :last_name, Shale::Type::String

  json do
    map 'firstName', to: :first_name
    map 'lastName', to: :last_name
  end
end

In XML schema ,xs:choice has a different meaning:

xml = <<~DATA
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Person">
    <xs:complexType>
      <xs:choice>
        <xs:element name="FirstName" type="xs:string"/>
        <xs:element name="LastName" type="xs:string"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>
DATA

puts Shale::Schema.from_xml([xml]).values[0]

it will give you:

class Person < Shale::Mapper
  attribute :first_name, Shale::Type::String
  attribute :last_name, Shale::Type::String

  xml do
    root 'Person'

    map_element 'FirstName', to: :first_name
    map_element 'LastName', to: :last_name
  end
end

If you want to generate schema from models, they are not supported as there is no way to mark attributes as belonging to union.

kgiszczak commented 1 year ago

Hey, Im closing this issue, if you have any other questions, let me know.