我正在尝试解析网络会话(通过MoyaProvider完成)导致的JSON对象。返回的JSON对象中嵌套了JSON数组。看起来像这样:
编辑:链接到json文件在这里。 results.json
#%%
# imports
import datetime, time
import pandas as pd
import numpy as np
import statsmodels.api as sm
from collections import OrderedDict
# your data in a more easily reprodicible format
data = {'Date': ['2019-03-31 08:59:59.999', '2019-03-31 09:59:59.999', '2019-03-31 10:59:59.999',
'2019-03-31 11:59:59.999', '2019-03-31 12:59:59.999', '2019-03-31 13:59:59.999',
'2019-03-31 14:59:59.999', '2019-03-31 15:59:59.999', '2019-03-31 16:59:59.999'],
'Price': [1660, 1657, 1656, 1652, 1646, 1645, 1650, 1669, 1674]}
# function to make a useful time structure as independent variable
def myTime(date_time_str):
date_time_obj = datetime.datetime.strptime(date_time_str, '%Y-%m-%d %H:%M:%S.%f')
return(time.mktime(date_time_obj.timetuple()))
# add time structure to dataset
data['Time'] = [myTime(obs) for obs in data['Date']]
# time for pandas
df = pd.DataFrame(data)
# Function for rolling OLS of a desired window size on a pandas dataframe
def RegressionRoll(df, subset, dependent, independent, const, win):
"""
RegressionRoll takes a dataframe, makes a subset of the data if you like,
and runs a series of regressions with a specified window length, and
returns a dataframe with BETA or R^2 for each window split of the data.
Parameters:
===========
df -- pandas dataframe
subset -- integer - has to be smaller than the size of the df or 0 if no subset.
dependent -- string that specifies name of denpendent variable
independent -- LIST of strings that specifies name of indenpendent variables
const -- boolean - whether or not to include a constant term
win -- integer - window length of each model
Example:
========
df_rolling = RegressionRoll(df=df, subset = 0,
dependent = 'Price', independent = ['Time'],
const = False, win = 3)
"""
# Data subset
if subset != 0:
df = df.tail(subset)
else:
df = df
# Loopinfo
end = df.shape[0]+1
win = win
rng = np.arange(start = win, stop = end, step = 1)
# Subset and store dataframes
frames = {}
n = 1
for i in rng:
df_temp = df.iloc[:i].tail(win)
newname = 'df' + str(n)
frames.update({newname: df_temp})
n += 1
# Analysis on subsets
df_results = pd.DataFrame()
for frame in frames:
#debug
#print(frames[frame])
# Rolling data frames
dfr = frames[frame]
y = dependent
x = independent
# Model with or without constant
if const == True:
x = sm.add_constant(dfr[x])
model = sm.OLS(dfr[y], x).fit()
else:
model = sm.OLS(dfr[y], dfr[x]).fit()
# Retrieve price and price prediction
Prediction = model.predict()[-1]
d = {'Price':dfr['Price'].iloc[-1], 'Predict':Prediction}
df_prediction = pd.DataFrame(d, index = dfr['Date'][-1:])
# Retrieve parameters (constant and slope, or slope only)
theParams = model.params[0:]
coefs = theParams.to_frame()
df_temp = pd.DataFrame(coefs.T)
df_temp.index = dfr['Date'][-1:]
# Build dataframe with Price, Prediction and Slope (+constant if desired)
df_temp2 = pd.concat([df_prediction, df_temp], axis = 1)
df_temp2=df_temp2.rename(columns = {'Time':'Slope'})
df_results = pd.concat([df_results, df_temp2], axis = 0)
return(df_results)
# test run
df_rolling = RegressionRoll(df=df, subset = 0,
dependent = 'Price', independent = ['Time'],
const = False, win = 3)
print(df_rolling)
现在使用Moya,我可以通过使用Moya.Response API来获取数据:
{
“resultCount” : 50,
“results” :
[
{
“data1”: 1
“data2”: 2
},
{
“data1”: 1
“data2”: 2
},
{
“data1”: 1
“data2”: 2
}
]
}
但是我不想这样做,我想将其映射到我的Model结构。我在下面做了这样的事情。我已经通过OPTION + MouseHover检查了objMovie的类型为[Movie]
let jsonObj = try response.mapJSON()
我已经使用类似的技术在线上了一个教程,但是我 不明白为什么objMovie为什么不包含执行以上行后的返回值。我尝试做
let objMovie = try response.map(ITunesSearchResults<Movie>.self).results
但控制台上没有任何显示。
那有什么用?
以下是一些代码段。 ITunesSearchResults在哪里:
print(obj.< propertyofMovie >)
我的电影结构是这样。它符合JSON嵌套数组属性中找到的键值。
struct ITunesSearchResults<T: Decodable>: Decodable {
let results: [T]
}
答案 0 :(得分:0)
首先,当您想要使用Data
对JSON进行解码时,请使用Moya
的{{1}}响应
Decodable
您的let data = response.data
结构太复杂了,显式Movie
并且根本不需要CodingKeys
方法,您可以免费获得它们。足够了:
init
请注意,struct ITunesSearchResults<T: Decodable>: Decodable {
let results: [T]
}
struct Movie: Decodable
{
let trackId: Int
let trackName: String
let trackGenre: String?
let trackPrice: Double?
let longDescription: String
}
是trackPrice
,Double
和trackGenre
是可选的。
现在只需解码
trackPrice
注意:
从不使用
之类的语法do {
let result = try JSONDecoder().decode(ITunesSearchResults<Movie>.self, from: data)
print(result)
} catch { print(error) }
有try container.decode(Int?.self, forKey: .trackPrice)
decodeIfPresent
巨大的好处是,如果存在密钥,但是类型错误,例如在这种具体情况下,它将引发错误。