gpt4 book ai didi

types - 如何使用 Js.Dict.t 类型为 Js.Dict.get

转载 作者:行者123 更新时间:2023-12-01 10:21:52 24 4
gpt4 key购买 nike

我正在尝试将一些 JS 转换为 Reason,在此过程中我需要键入 JSON 响应并检查对象中是否存在键。

这是我当前的代码:

let api_key = "";
let api_url = "http://ws.audioscrobbler.com/2.0";
let method = "user.getRecentTracks";
let user = "montogeek";

type trackAttr = {
nowplaying: bool
};

type artistT = {
text: string
}

type trackT = {
attr: trackAttr,
name: string,
artist: artistT
};

type recentTrackT = {
track: array(Js.Dict.t(trackT))
};

type response = {
recenttracks: recentTrackT
};

Js.Promise.(Fetch.fetch(api_url ++ "?method=" ++ method ++ "&" ++ user ++ "=" ++ user ++ "&limit=1&format=json&api_key=" ++ api_key)
|> then_(Fetch.Response.json)
|> then_(json: response => {
let lasttrack = json.recenttracks.track[0];

let online = switch (Js.Dict.get(lasttrack, "attr")) {
| None => false
| Some(track) => track.attr.nowplaying
};
let info = online ? "Enjoying" ++ lasttrack.name ++ "by " ++ lasttrack.artist["#text"] ++ "}" : "";

{ online, info }
}));

目前我收到这个错误:

We've found a bug for you!
/Users/montogeek/Infinite/Lov/online/src/lastfm.re 37:41-49

35 ┆ | Some(track) => track.attr.nowplaying
36 ┆ };
37 ┆ let info = online ? "Enjoying" ++ lasttrack.name ++ "by " ++ lasttrack
.artist["#text"] ++ "}" : "";
38 ┆
39 ┆ { online, info }

This has type:
Js.Dict.t(trackT) (defined as Js.Dict.t(trackT))
But somewhere wanted:
trackT

我无法删除 Js.Dict.t 类型,因为 Js.Dict.get 不喜欢它。

我怎样才能输入响应以使其有效?

谢谢!

最佳答案

您可能想尝试以较小的增量构建它,因为您已经在这里给自己挖了一个很深的坑。

首先,您是根据记录类型而不是 JS 对象类型来描述您的 JSON 响应。

这是一个记录类型:

type  t = { foo: string };

这是一个 JS 对象类型:

type t = {. "foo": string };

一个微妙但非常重要的区别。

其次,Js.Dict.t(trackT) 并不是您所想的那样(尽管我也不清楚它到底是什么)。它描述了一个用作散列的 JS 对象,具有 String 类型的键和 trackT 类型的值。这看起来像是解决第一个问题的尝试,但只会让漏洞变得更深,所以也许只是恢复它。

第三,您不能仅通过注释来断言 JSON 响应具有 response 类型。这是一个健全的类型系统,它只会给你一个类型错误。如果你想绕过类型系统(这几乎总是一个坏主意)你必须更加明确。

还有一些其他的小错误,但这超出了本文的范围。

所以你应该做的是以下两件事之一:

正确的方法是使用像bs-json 这样的库。将 JSON 响应解码为您已经定义的记录类型,在应该完成的边界处验证数据的形状,然后继续正常使用记录类型:

/* assume record types are defined above */

module Decode = {
open Json.Decode;

let trackAttr = json => {
nowplaying: json |> field("nowplaying", bool)
};

let artist = json => {
text: json |> field("text", string)
}

let track = json => {
attr: json |> optional(field("attr", trackAttr)),
name: json |> field("name", string),
artist: json |> field("artist", artist)
};

let recentTrack = json => {
track: json |> field("track", array(track))
};

let response = json => {
recenttracks: json |> field("recenttracks", recentTrack)
};
};

Js.Promise.(Fetch.fetch(api_url ++ "?method=" ++ method ++ "&" ++ user ++ "=" ++ user ++ "&limit=1&format=json&api_key=" ++ api_key)
|> then_(Fetch.Response.json)
|> then_(json => {
let response = Decode.response(json);
let lasttrack = response.recenttracks.track[0];
...
}));

快速而肮脏的方法是将记录类型转换为 JS 对象类型,然后断言数据具有该形状,从而绕过类型系统。如果它没有您期望的形状,您可能会在任何地方遇到运行时错误,并且需要手动追踪问题的根源。这可能是这样的:

type trackAttr = {.
"nowplaying": bool
};

type artistT = {.
"text": string
}

type trackT = {.
"attr": trackAttr,
"name": string,
"artist": artistT
};

type recentTrackT = {.
"track": array(trackT)
};

type response = {.
"recenttracks": recentTrackT
};

external unsafeCastJsonAsResponse : Js.Json.t => response = "%identity";

Js.Promise.(Fetch.fetch(api_url ++ "?method=" ++ method ++ "&" ++ user ++ "=" ++ user ++ "&limit=1&format=json&api_key=" ++ api_key)
|> then_(Fetch.Response.json)
|> then_(json => {
let response = unsafeCastJsonAsResponse(json);
let lasttrack = response##recenttracks##track[0];
...
}));

关于types - 如何使用 Js.Dict.t 类型为 Js.Dict.get,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50493259/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com