如何在 hx-post 中发送对象数据 - JSON.stringify 用引号包围数组

问题描述 投票:0回答:1

我试图通过 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([])
都返回
'[]'

我该如何解决这个问题?我查了很多网站都没有找到解决办法。

javascript json htmx
1个回答
1
投票

可能是您没有导入

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>

getFilesDTO()

    <script>
      // dummy files for testing 
      const files = [
        {name: "abc.js", size: 100 * 1024 * 1024},
        {name: "def.js", size: 200 * 1024 * 1024}
      ]
      function getFilesDTO() {
        return files.map((file) => {
          return {
            name: file.name,
            extension: file.name.split('.').pop(),
            sizeMB: file.size / 1024 / 1024
          }
        })
      }
    </script>

在控制台网络选项卡中,它显示了一个未引用的文件数组

enter image description here


或者,您可以在

<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>
© www.soinside.com 2019 - 2024. All rights reserved.