Как соответствовать и заполнить общую пиддантскую модель с глубоко вложенными полями из аналогичных, но связанных с соглPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Как соответствовать и заполнить общую пиддантскую модель с глубоко вложенными полями из аналогичных, но связанных с согл

Сообщение Anonymous »

Я строю обобщенную модель Pydantic (давайте назовем ее модель X), которую я хочу использовать для сопоставления и извлечения значений из нескольких различных схем JSON (модель A, B, C и т. Д.). Эти схемы получают через API и не могут быть изменены в источнике. (DATAMODEL_CODE_GENERATOR) < /li>
[*] Получить мою обобщенную схему -> генерировать пижантическую модель x < /li>
Создать пустой экземпляр обобщенной модели x (проблематично из -за необходимых полей) < /li>
Совместитель A с моделью x < /li>
x. Если битх имеет систему. Строка в одной схеме и списке в другой) или ($ ref/имена подкласса различаются).
Требуемые поля в модели x делают «пустую, но полностью структурированную» версию. /> Создание полностью структурированного (но неопустокованного) экземпляра x < /li>
Совместные пути /типы между a и x, даже если имена $ refs различаются < /li>
Создать для гибкой популяции и проверки общих структур < /li>
< /ul>
?? Любой совет:

Что было бы хорошей стратегией для такого рода абстракции схемы и сопоставления экземпляров? class = "lang-json prettyprint-override">{
"required": ["systems", "results"],
"properties": {
"systems": {
"$ref": "#/definitions/System"
},
"results": {
"$ref": "#/definitions/ResultList"
}
},
"definitions": {
"System": {
"type": "object",
"required": ["vendor", "model", "type", "operator"],
"properties": {
"vendor": { "type": "string" },
"model": { "type": "string" },
"type": { "type": "string" },
"operator": { "type": "string" }
}
},
"Result": {
"type": "object",
"properties": {
"x": { "type": "integer" },
"y": { "type": "integer" }
},
"required": ["x", "y"]
},
"ResultList": {
"type": "array",
"items": { "$ref": "#/definitions/Result" }
}
}
}
< /code>
упрощенный пример схемы A < /h2>
{
"$schema": "http://json-schema.org/draft-07/schema",
"type": "object",
"required": ["systems", "users", "results"],
"properties": {
"systems": {
"type": "array",
"items": { "$ref": "#/definitions/turbineSystem" }
},
"users": {
"type": "array",
"items": { "$ref": "#/definitions/User" }
},
"results": {
"$ref": "#/definitions/ResultList"
}
},
"definitions": {
"turbineSystem": {
"type": "object",
"required": ["vendor", "model", "type", "serial_number"],
"properties": {
"vendor": { "type": "string" },
"model": { "type": "string" },
"type": {
"type": "array",
"items": { "type": "string" }
},
"serial_number": { "type": "string" }
}
},
"User": {
"type": "object",
"properties": {
"name": { "type": "string" }
}
},
"turbineResult": {
"type": "object",
"required": ["x", "y"],
"properties": {
"x": { "type": "string" }, // ← conflict: was integer in Generic
"y": { "type": "integer" }
}
},
"ResultList": {
"type": "array",
"items": { "$ref": "#/definitions/turbineResult" } // ← conflict: reference is different in Generic
}
}
}

я попробовал:

Сопоставьте структуру схемы JSON (модель A) с более простой общей/обобщенной схемой через модели пиданты для обеспечения типов. /> < /ul>
i ожидал: < /strong> < /p>

Для создания «шаблона» экземпляра модели x со значениями заполнителя /по умолчанию, чтобы его можно было заполнить с помощью модели x только из модели. и совпадать с полями (например, Systems []. Model, Results []. X и т. Д.)import json
import os
from datamodel_code_generator.parser.jsonschema import JsonSchemaParser

import tempfile

import importlib.util
import sys

from pydantic import BaseModel

## Works as it should
def get_pydantic_model_from_jsonschema(json_schema: dict) -> type[BaseModel]:
parser = JsonSchemaParser(str(json_schema))

model_code = parser.parse()

# Save to a temporary .py file - i only need to model during runtime
with tempfile.NamedTemporaryFile(delete=False, suffix=".py") as temp_file:
temp_file.write(model_code.encode('utf-8'))
temp_file_path = temp_file.name

# Import the generated module
spec = importlib.util.spec_from_file_location("generated_model", temp_file_path)
generated_model = importlib.util.module_from_spec(spec)
sys.modules["generated_model"] = generated_model
spec.loader.exec_module(generated_model)

os.remove(temp_file_path)

model_class = getattr(generated_model, "Model")

return model_class

# Doesn't work
def create_empty_instance(model_class: type[BaseModel]) -> BaseModel:
# Create an empty instance of the Pydantic model, with default values
def fill(model_cls: type[BaseModel]) -> dict:
result = {}
for field_name, field_info in model_cls.model_fields.items():
field_type = field_info.annotation
if field_type == str:
result[field_name] = ""
elif field_type == int:
result[field_name] = 0
elif field_type == bool:
result[field_name] = False
else:
result[field_name] = None
return result
return model_class(**fill(model_class))

# doesn't work
def populate_model_from_another(source_model: BaseModel, target_model: BaseModel) -> BaseModel:
# Copy matching fields from source model to target model
def add_matching_field_values(source: any, target: any):
for field in source.model_fields:
if field in target.model_fields:
src_val = getattr(source, field)
tgt_val = getattr(target, field)

# Recursive step for nested models
if isinstance(src_val, BaseModel) and isinstance(tgt_val, BaseModel):
add_matching_field_values(src_val, tgt_val)
elif isinstance(src_val, list) and isinstance(tgt_val, list):
for src_item, tgt_item in zip(src_val, tgt_val):
add_matching_field_values(src_item, tgt_item)
else:
setattr(target, field, src_val)

add_matching_field_values(source_model, target_model)

return target_model

# ___________________________________________________________________________________
# Load Model A (source) schema and instance
with open('model_a_schema.json', 'r') as f:
model_a_schema = json.load(f)

with open('model_a_data.json', 'r') as f:
model_a_data = json.load(f)

model_a_class = get_pydantic_model_from_jsonschema(model_a_schema)
model_a_instance = model_a_class(**model_a_data)

# Load Generic Model X schema
with open('generic_model_x_schema.json', 'r') as f:
generic_model_x_schema = json.load(f)

generic_model_x_class = get_pydantic_model_from_jsonschema(generic_model_x_schema)

# Does't work: Create empty instance/template
generic_model_x_instance = create_empty_instance(generic_model_x_class)

# Does't work: Populate the Generic Model X instance with matching data from Model A
populated_generic_model_x = populate_model_from_another(model_a_instance, generic_model_x_instance)

print(populated_generic_model_x)


Подробнее здесь: https://stackoverflow.com/questions/796 ... fields-fro
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»