Datamodel-code-generator: json_schema_data_formats fail when looking up 'array'

Created on 24 Jun 2020  ยท  10Comments  ยท  Source: koxudaxi/datamodel-code-generator

When trying to convert file data.json to model.py, I get a
keyerror on line 171 of jsonschema.py when the type in types is 'array'.

To Reproduce

Example schema:
```json

bug released

All 10 comments

When I amended the json_schema_data_formats and added:

'array': {'default': Types.array}

and added Types.array: DataType(type='list'), to typ_map in types.py

this fixed the issue.

I am not sure if this fixes any corner cases, but I do believe json 'array' maps to a list.

@javierabosch
Thank you for creating this issue.

and added Types.array: DataType(type='list'), to typ_map in types.py

This approach is not bad, However, Python List needs sub types like List[str]
The generator use a method which can parse array object to resolve subtypes of List.
https://github.com/koxudaxi/datamodel-code-generator/blob/01e9e58e92e44c385133b80c01caa475548929cd/datamodel_code_generator/parser/jsonschema.py#L201

I would use the method to parse your array object. I don't know why It was not used in your case.
Would you please put the json file?
I want to resolve this problem.

Hi @koxudaxi ,

The json file is quite large. Is there anyway I can email it to you?

I saw the function you referenced in the code, but I was just monkey patching as I went along, hoping down the pipeline it would use that function.

I sent the json file to your email.

@javierabosch
Thank you for your email.
I have fixed a problem which is a nested array.
I released a new version as 0.5.11

But, I found other problems to generate models from your json data.

  1. Need calling update_forward_refs for MediaItem after all dependency models are defined.
    I will fix the problem when I refactor a function referencing class which is related to the issue https://github.com/koxudaxi/datamodel-code-generator/issues/145
    It means a feature is broken which is referencing class.

  2. change types of some field to Optional
    the code generator uses genson to convert Json data to JSON schema. the problem happens is in genson.
    You should change types to Optional manually after you generate models.

@javierabosch

  1. Need calling update_forward_refs for MediaItem after all dependency models are defined.

Sorry, I mistake. It's no problem.

I believe this issue was resolved. Can I close this issue?

Hi, I'm on 0.5.34 and the KeyError: 'array' issue still appears. I was able to track it down to the following case:

{
  "my_obj": [
    {
      "items": null
    },
    {
      "items": []
    }
  ]
}

It doesn't matter whether the null or the [] is defined first.

The schema generated from this is:

{
    "$schema": "http://json-schema.org/schema#",
    "type": "object",
    "properties": {
        "my_obj": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "items": {
                        "type": [
                            "array",
                            "null"
                        ]
                    }
                },
                "required": [
                    "items"
                ]
            }
        }
    },
    "required": [
        "my_obj"
    ]
}

Traceback:

Traceback (most recent call last):

  File "C:\projects\josxabot\app\modules\josxa_private\pydantic_model_gen\directory_watcher.py", line 92, in run_conversion
    generate(
    โ”” <function generate at 0x00000251AF436CA0>

  File "C:\Users\INT002327\AppData\Local\pypoetry\Cache\virtualenvs\josxabot-c3BmTbt9-py3.8\lib\site-packages\datamodel_code_generator\__init__.py", line 185, in generate
    result = parser.parse()
             โ”‚      โ”” <function Parser.parse at 0x00000251AF436A60>
             โ”” <datamodel_code_generator.parser.jsonschema.JsonSchemaParser object at 0x00000251AF20E6A0>

  File "C:\Users\INT002327\AppData\Local\pypoetry\Cache\virtualenvs\josxabot-c3BmTbt9-py3.8\lib\site-packages\datamodel_code_generator\parser\base.py", line 351, in parse
    self.parse_raw()
    โ”‚    โ”” <function JsonSchemaParser.parse_raw at 0x00000251B1703430>
    โ”” <datamodel_code_generator.parser.jsonschema.JsonSchemaParser object at 0x00000251AF20E6A0>

  File "C:\Users\INT002327\AppData\Local\pypoetry\Cache\virtualenvs\josxabot-c3BmTbt9-py3.8\lib\site-packages\datamodel_code_generator\parser\jsonschema.py", line 687, in parse_raw
    self.parse_raw_obj(obj_name, raw_obj, [])
    โ”‚    โ”‚             โ”‚         โ”” {'$schema': 'http://json-schema.org/schema#', 'type': 'object', 'properties': {'my_obj': {'type': 'array', 'items': {'type': ...
    โ”‚    โ”‚             โ”” 'Model'
    โ”‚    โ”” <function JsonSchemaParser.parse_raw_obj at 0x00000251B17033A0>
    โ”” <datamodel_code_generator.parser.jsonschema.JsonSchemaParser object at 0x00000251AF20E6A0>

  File "C:\Users\INT002327\AppData\Local\pypoetry\Cache\virtualenvs\josxabot-c3BmTbt9-py3.8\lib\site-packages\datamodel_code_generator\parser\jsonschema.py", line 671, in parse_raw_obj
    self.parse_object(name, obj, path)
    โ”‚    โ”‚            โ”‚     โ”‚    โ”” []
    โ”‚    โ”‚            โ”‚     โ”” JsonSchemaObject(items=None, uniqueItem=None, type='object', format=None, pattern=None, minLength=None, maxLength=None, minim...
    โ”‚    โ”‚            โ”” 'Model'
    โ”‚    โ”” <function JsonSchemaParser.parse_object at 0x00000251B1703040>
    โ”” <datamodel_code_generator.parser.jsonschema.JsonSchemaParser object at 0x00000251AF20E6A0>

  File "C:\Users\INT002327\AppData\Local\pypoetry\Cache\virtualenvs\josxabot-c3BmTbt9-py3.8\lib\site-packages\datamodel_code_generator\parser\jsonschema.py", line 424, in parse_object
    fields = self.parse_object_fields(obj, path)
             โ”‚    โ”‚                   โ”‚    โ”” []
             โ”‚    โ”‚                   โ”” JsonSchemaObject(items=None, uniqueItem=None, type='object', format=None, pattern=None, minLength=None, maxLength=None, minim...
             โ”‚    โ”” <function JsonSchemaParser.parse_object_fields at 0x00000251B16E0F70>
             โ”” <datamodel_code_generator.parser.jsonschema.JsonSchemaParser object at 0x00000251AF20E6A0>

  File "C:\Users\INT002327\AppData\Local\pypoetry\Cache\virtualenvs\josxabot-c3BmTbt9-py3.8\lib\site-packages\datamodel_code_generator\parser\jsonschema.py", line 331, in parse_object_fields
    array_field, array_field_classes = self.parse_array_fields(
                                       โ”‚    โ”” <function JsonSchemaParser.parse_array_fields at 0x00000251B17030D0>
                                       โ”” <datamodel_code_generator.parser.jsonschema.JsonSchemaParser object at 0x00000251AF20E6A0>

  File "C:\Users\INT002327\AppData\Local\pypoetry\Cache\virtualenvs\josxabot-c3BmTbt9-py3.8\lib\site-packages\datamodel_code_generator\parser\jsonschema.py", line 458, in parse_array_fields
    type=self.parse_object(
         โ”‚    โ”” <function JsonSchemaParser.parse_object at 0x00000251B1703040>
         โ”” <datamodel_code_generator.parser.jsonschema.JsonSchemaParser object at 0x00000251AF20E6A0>

  File "C:\Users\INT002327\AppData\Local\pypoetry\Cache\virtualenvs\josxabot-c3BmTbt9-py3.8\lib\site-packages\datamodel_code_generator\parser\jsonschema.py", line 424, in parse_object
    fields = self.parse_object_fields(obj, path)
             โ”‚    โ”‚                   โ”‚    โ”” ['my_obj']
             โ”‚    โ”‚                   โ”” JsonSchemaObject(items=None, uniqueItem=None, type='object', format=None, pattern=None, minLength=None, maxLength=None, minim...
             โ”‚    โ”” <function JsonSchemaParser.parse_object_fields at 0x00000251B16E0F70>
             โ”” <datamodel_code_generator.parser.jsonschema.JsonSchemaParser object at 0x00000251AF20E6A0>

  File "C:\Users\INT002327\AppData\Local\pypoetry\Cache\virtualenvs\josxabot-c3BmTbt9-py3.8\lib\site-packages\datamodel_code_generator\parser\jsonschema.py", line 391, in parse_object_fields
    field_types = self.get_data_type(field)
                  โ”‚    โ”‚             โ”” JsonSchemaObject(items=None, uniqueItem=None, type=['array', 'null'], format=None, pattern=None, minLength=None, maxLength=No...
                  โ”‚    โ”” <function JsonSchemaParser.get_data_type at 0x00000251B169AF70>
                  โ”” <datamodel_code_generator.parser.jsonschema.JsonSchemaParser object at 0x00000251AF20E6A0>

  File "C:\Users\INT002327\AppData\Local\pypoetry\Cache\virtualenvs\josxabot-c3BmTbt9-py3.8\lib\site-packages\datamodel_code_generator\parser\jsonschema.py", line 190, in get_data_type
    return [

  File "C:\Users\INT002327\AppData\Local\pypoetry\Cache\virtualenvs\josxabot-c3BmTbt9-py3.8\lib\site-packages\datamodel_code_generator\parser\jsonschema.py", line 192, in <listcomp>
    json_schema_data_formats[t][format_],
    โ”‚                        โ”‚  โ”” 'default'
    โ”‚                        โ”” 'array'
    โ”” {'integer': {'int32': <Types.int32: 2>, 'int64': <Types.int64: 3>, 'default': <Types.integer: 1>}, 'number': {'float': <Types...

KeyError: 'array'

@koxudaxi would you like me to create a fresh issue for this?

My super hacky workaround:

def normalize_null_arrays(obj: Any):
    """ Recursively replace "null" dict values with empty lists if another item in the same list contains an empty [] """
    if isinstance(obj, dict):
        for val in obj.values():
            normalize_null_arrays(val)
        return

    if not isinstance(obj, list):
        return

    key_has_null_map = dict()
    key_has_array_map = dict()

    for i in obj:
        if not isinstance(i, dict):
            break

        for k, v in i.items():
            if v is None:
                key_has_null_map[k] = True
            if v == []:
                key_has_array_map[k] = True

    for i in obj:
        if not isinstance(i, dict):
            break

        for k, v in i.items():
            if k in key_has_array_map and k in key_has_null_map and v is None:
                i[k] = []

normalize_null_arrays(some_json_data)

@JosXa
Thank you for reporting the problem.

would you like me to create a fresh issue for this?

Yes, please.

I will check the problem tomorrow.

Alright, will do ๐Ÿ‘

Was this page helpful?
0 / 5 - 0 ratings

Related issues

languitar picture languitar  ยท  3Comments

elonzh picture elonzh  ยท  4Comments

ioggstream picture ioggstream  ยท  6Comments

HuiiBuh picture HuiiBuh  ยท  4Comments

MikeZaharov picture MikeZaharov  ยท  3Comments