Как преобразовать данные JSON в формат Avro с помощью Python
Я хотел бы преобразовать приведенные ниже данные JSON в формат avro. Я использовал приведенный ниже фрагмент кода для записи данных JSON в формате avro, но получил ошибку. Если бы кто-нибудь мог с этим помочь, было бы здорово.
from fastavro import writer, reader, schema
from rec_avro import to_rec_avro_destructive, from_rec_avro_destructive, rec_avro_schema
def getweatherdata():
url = 'https://api.openweathermap.org/data/2.5/onecall?lat=33.441792&lon=-94.037689&exclude=hourly,daily&appid=' + apikey
response = requests.get(url)
data = response.text
return data
def turntoavro():
avro_objects = (to_rec_avro_destructive(rec) for rec in getweatherdata())
with open('json_in_avro.avro', 'wb') as f_out:
writer(f_out, schema.parse_schema(rec_avro_schema()), avro_objects)
turntoavro()
Error details:
File "fastavro/_write.pyx", line 269, in fastavro._write.write_record
TypeError: Expected dict, got str
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "datalake.py", line 30, in <module>
turntoavro()
File "datalake.py", line 26, in turntoavro
writer(f_out, schema.parse_schema(rec_avro_schema()), avro_objects)
File "fastavro/_write.pyx", line 652, in fastavro._write.writer
File "fastavro/_write.pyx", line 605, in fastavro._write.Writer.write
File "fastavro/_write.pyx", line 341, in fastavro._write.write_data
File "fastavro/_write.pyx", line 278, in fastavro._write.write_record
AttributeError: 'str' object has no attribute 'get'
Пример данных:
{
"lat": 33.44,
"lon": -94.04,
"timezone": "America/Chicago",
"timezone_offset": -18000
}
2 ответа
Как упоминалось в одном из ответов, вы, вероятно, захотите использовать response.json()
скорее, чем response.text
так что вы получите фактический словарь JSON.
Однако другая проблема заключается в том, что getweatherdata()
возвращает единственный словарь, поэтому, когда вы это сделаете avro_objects = (to_rec_avro_destructive(rec) for rec in getweatherdata())
вы перебираете ключи в этом словаре. Вместо этого вы должны сделатьavro_objects = [to_rec_avro_destructive(getweatherdata())]
Я считаю, что этот код должен работать на вас:
from fastavro import writer, reader, schema
from rec_avro import to_rec_avro_destructive, from_rec_avro_destructive, rec_avro_schema
def getweatherdata():
url = 'https://api.openweathermap.org/data/2.5/onecall?lat=33.441792&lon=-94.037689&exclude=hourly,daily&appid=' + apikey
response = requests.get(url)
data = response.json()
return data
def turntoavro():
avro_objects = [to_rec_avro_destructive(getweatherdata())]
with open('json_in_avro.avro', 'wb') as f_out:
writer(f_out, schema.parse_schema(rec_avro_schema()), avro_objects)
turntoavro()
Чтобы получить ответ на сделанный вами запрос, вы использовали response.text
который возвращает ответ в виде строки, а не в формате JSON. Вы должны использоватьresponse.json()
вместо этого иметь его в формате JSON:
import json
def getweatherdata():
url = 'https://api.openweathermap.org/data/2.5/onecall?lat=33.441792&lon=-94.037689&exclude=hourly,daily&appid=' + apikey
response = requests.get(url)
data = response.json()
return data
def turntoavro():
avro_objects = (to_rec_avro_destructive(rec) for rec in getweatherdata())
with open('json_in_avro.avro', 'wb') as f_out:
writer(f_out, schema.parse_schema(rec_avro_schema()), avro_objects)
turntoavro()