json - TypeScript:将原始数据解析为接口(interface)

标签 json typescript

在 Typescript(特别是 React with hooks)中,我试图从 OAuth 回调中解析一些 URL 哈希数据,并在我的组件中使用它。

我可以通过调用 window.location.hash 来解析我的数据

const hash = window.location.hash.substr(1);
const oauthData = hash.split('&')
  .map(v => v.split('='))
  .reduce((pre, [key, value]) => (
    key == 'scope' ? {...pre, [key]: value.split('+')} : {...pre, [key]: value}
  ), {});
{
  "access_token": "eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyMkJCWVkiLCJzdWIiOiI1TkZCTFgiLCJpc3MiOiJGaXRiaXQiLCJ0eXAiOiJhY2Nlc3NfdG9rZW4iLCJzY29wZXMiOiJyc29jIHJhY3QgcnNldCBybG9jIHJ3ZWkgcmhyIHJudXQgcnBybyByc2xlIiwiZXhwIjoxNTc4NTQ3NzkxLCJpYXQiOjE1NzgyMDQzOTF9.qLl0L5DthFu3NxeLodotPsPljYMWgw1AvKj2_i6zilU",
  "user_id": "5NFBLX",
  "scope": [
    "heartrate",
    "nutrition",
    "location",
    "sleep",
    "activity",
    "weight",
    "social",
    "profile",
    "settings"
  ],
  "token_type": "Bearer",
  "expires_in": "343400"
}

太棒了!现在我想将所有这些信息传递到我的组件中,这就是事情变得有点困惑的地方,我无法找到将这些数据放入我的组件的方法,因为我破坏了类型安全。

我的组件是这样构建的

export interface IOAuthProps {
  accessToken: string
  userID: string
  scope: string[]
  expiresIn: number
}

const OAuthFun: React.FC<IOAuthProps> = (props) => {

  const [ac] = useState(props.accessToken)
  return (
    <div>
      access token = {ac}
    </div>
  )
}

export default OAuthFun;

我已经尝试了这些看似相同的事物的排列(为简洁起见,我将省略其他属性):

非工作示例:甚至无法索引 oauthData,因为它属于 {}

<OAuthFun accessToken={oauthData['access_token'] as string}/>

因为我什至无法将原始 json 对象作为字典进行索引,所以我想我需要在正在构建的对象上创建一些类型安全:

  const oauthData = hash.split('&')
    .map(v => v.split('='))
    .reduce((pre, [key, value]) => (
      key == 'scope' ? {...pre, [key]: value.split('+')} : {...pre, [key]: value}
    ), {access_token: String, user_id: String, scope: [], expires_in: Number});

但是,这会破坏我的 reduce 调用中的表达式:没有重载匹配此调用。 这让我相信我需要一些更简洁的方法来解析原始数据,但我我真的不确定该怎么做。

我想我可以将其直接从原始数据转换为界面,但原始数据的命名约定使用 underscore_casing 而不是 camelCasing。此外,如果我更改大小写而不是学习如何规范化数据,它只是回避问题而不解决问题。

将原始数据直接放入界面的正确方法是什么?

最佳答案

根据评论,我能够拼凑出这个解决方案。

import React from 'react';

export interface IOAuthProps {
  accessToken: string
  userID: string
  scope: string[]
  expiresIn: number
}

export function ParseOAuthProperties(rawHashProperties: string): IOAuthProps {
  const rawData = rawHashProperties.substr(1)
    .split('&')
    .map(v => v.split('='))
    .reduce((pre, [key, value]) => (
      {...pre, [key]: value}
    ), {access_token: "", user_id: "", scope: "", expires_in: ""});
    const normalizedData: IOAuthProps = {
      accessToken: rawData.access_token,
      userID: rawData.user_id,
      scope: rawData.scope.split('+'),
      expiresIn: Number(rawData.expires_in),
    }
    return normalizedData;
}

const OAuthFun: React.FC<IOAuthProps> = (props) => {
  return (
    <div>
      <div>access token = {props.accessToken}</div>
      <div>user id = {props.userID}</div>
      <div>scope = {props.scope}</div>
      <div>expires in = {props.expiresIn}</div>
    </div>
  )
}

export default OAuthFun;

现在我可以采用我的方法,它封装了规范化并返回接口(interface),并从我的父组件中使用它:

import React from 'react';
import OAuthFun, {ParseOAuthProperties, IOAuthProps} from './OAuthFun'

const App: React.FC = () => {
  const props: IOAuthProps = ParseOAuthProperties(window.location.hash)
  return (
    <div className="App">
      {/* Note, you can pass the interface wholesale with the spread operator */}
      <OAuthFun {...props} />
    </div>
  );
}

export default App;

关于json - TypeScript:将原始数据解析为接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59597876/

相关文章:

javascript - typescript 编译时错误

javascript - 通用部分应用程序的 Varargs 函数参数不进行类型检查

json - 使用 jq 计算缺少键的记录

java - 如何制作同时使用过滤器和 pretty-print 的 ObjectWriter?

typescript - 在 Angular cli 中导入 ng2-uploader

javascript - Typescript 指南给出 "Duplicate function implementation"警告

java - Spring Jackson @JsonFilter 示例

android - AppInventor 麻烦了! (JSON 索引)

java - 无法导入 Json 处理类

typescript - 使用 Typescript 的 angular2 上的开关按钮