我试图通过 REST API 从客户端发送数据到服务器,客户端只是一个包含 JavaScript 和 HTMX 的 HTML 页面,服务器是 Spring Boot。端点接受带有对象的 POST 请求:
public record FileMetadataDTO(Integer availabilityTime, FileDTO[] files) {}
public record FileDTO(String name, String extension, Integer sizeMB) {}
在客户端,我有一个按钮将请求发送到服务器:
<button id="upload-button"
hx-post="http://localhost:8080/api/v1/upload/metadata"
hx-headers='{"Content-Type": "application/json"}'
hx-ext="json-enc"
hx-vals='js:{"availabilityTime": 1, "files": getFilesDTO()}'
style="display: none;">Upload</button>
<label for="upload-button" style="border: 1px solid #ccc; padding: 6px 12px; cursor: pointer;">Upload files</label>
getFilesDTO()
函数返回一个字符串化数组:
function getFilesDTO() {
let filesDTO = [];
for (let i = 0; i < tuckedFiles.length; i++) {
filesDTO.push({
name: tuckedFiles[i].name,
extension: tuckedFiles[i].name.split('.').pop(),
sizeMB: tuckedFiles[i].size / 1024 / 1024
});
}
return JSON.stringify(filesDTO);
}
但是
JSON.stringify
用引号将数组括起来,服务器无法反序列化它:
{"availabilityTime":"1","files":"[{\"name\":\"a.txt\",\"extension\":\"txt\",\"sizeMB\":0.00022220611572265625},{\"name\":\"another_file.txt\",\"extension\":\"txt\",\"sizeMB\":0.000003814697265625}]"}
有效负载为:
{"availabilityTime":"1","files":[{"name":"a.txt","extension":"txt","sizeMB":0.00022220611572265625},{"name":"another_file.txt","extension":"txt","sizeMB":0.000003814697265625}]}
但无论如何我都不能让
JSON.stringify
那样做。我在Chrome和Edge的控制台中尝试了一下,看看我的代码是否有问题,但是两个浏览器控制台中的JSON.stringify([])
都返回'[]'
。
我该如何解决这个问题?我查了很多网站都没有找到解决办法。
可能是您没有导入
json-enc
扩展。
但是从
getFilesDTO()
返回的内容也会添加到有效负载中,因此如果您不需要字符串,请不要返回字符串!
如果我复制代码,添加显式导入(在 htmx 导入之后),它就可以正常工作。
快递服务器
app.get('/', (req, res) => {
res.send(`
<!DOCTYPE html>
<html>
<head>
...
<script src="https://unpkg.com/htmx.org"></script>
<script src="https://unpkg.com/htmx.org/dist/ext/json-enc.js"></script>
在控制台网络选项卡中,它显示了一个未引用的文件数组
或者,您可以在
json-enc
代码中编写脚本(它非常小)并使用它来调试
<script>
htmx.defineExtension('json-enc', {
onEvent: function (name, evt) {
if (name === "htmx:configRequest") {
evt.detail.headers['Content-Type'] = "application/json";
}
},
encodeParameters : function(xhr, parameters, elt) {
console.log('parameters', parameters)
xhr.overrideMimeType('text/json');
return (JSON.stringify(parameters));
}
});
</script>