首页 > 解决方案 > 简单的休息数据提供者不会接受 Odata 数据

问题描述

所以我使用的 API 使用的是 ODATA ( https://www.odata.org/ )。结果,这就是它返回时的样子

```

{"@odata.context":"http://localhost:5001/api/$metadata#apemp",
"value":[
{"EmpID":1,
"Abbr":"Admin",
"BadgeNo":null,
"ColorRef":0,
"ContactMethodID":null,
"DateHired":"2018-05-25T16:42:57-05:00"}

]```

我们的数据提供者看起来像这样

import { stringify } from 'query-string';
import {
   fetchUtils,
   GET_LIST,
   GET_ONE,
   GET_MANY,
   GET_MANY_REFERENCE,
   CREATE,
   UPDATE,
   UPDATE_MANY,
   DELETE,
   DELETE_MANY
} from 'react-admin';

...
   const convertHTTPResponse = (response, type, resource, params) => {
      const { headers, json } = response;
      switch (type) {
         case GET_LIST:
            return { data: json };
         case GET_MANY_REFERENCE:
            if (!headers.has('content-range')) {
               throw new Error(
                  'The Content-Range header is missing in the HTTP Response. The simple REST data provider expects responses for lists of resources to contain this header with the total number of results to build the pagination. If you are using CORS, did you declare Content-Range in the Access-Control-Expose-Headers header?'
               );
            }
            return {
               data: json,
               total: parseInt(
                  headers
                     .get('content-range')
                     .split('/')
                     .pop(),
                  10
               )
            };
         case CREATE:
            return { data: { ...params.data, id: json.id } };
         default:
            return { data: json };
      }
   };

   return (type, resource, params) => {
      // simple-rest doesn't handle filters on UPDATE route, so we fallback to calling UPDATE n times instead
      if (type === UPDATE_MANY) {
         return Promise.all(
            params.ids.map(id =>
               httpClient(`${apiUrl}/${resource}/${id}`, {
                  method: 'PUT',
                  body: JSON.stringify(params.data)
               })
            )
         ).then(responses => ({
            data: responses.map(response => response.json)
         }));
      }
      // simple-rest doesn't handle filters on DELETE route, so we fallback to calling DELETE n times instead
      if (type === DELETE_MANY) {
         return Promise.all(
            params.ids.map(id =>
               httpClient(`${apiUrl}/${resource}/${id}`, {
                  method: 'DELETE'
               })
            )
         ).then(responses => ({
            data: responses.map(response => response.json)
         }));
      }

      const { url, options } = convertDataRequestToHTTP(type, resource, params);
      return httpClient(url, options).then(response =>
         convertHTTPResponse(response, type, resource, params)
      );
   };
};

所以现在当我将该数据提供者指向 api 端点时,它看起来不像代码的格式。我得到错误

“对 'GET_LIST' 的响应必须类似于 { data : [...] },但接收到的数据不是数组。对于 'GET_LIST',dataProvider 可能是错误的”

我已经在我们之前的 API 中广泛使用了这个 dataprovider,它返回的数据略有不同。

因为 odata 返回一个对象,其中上下文和 url 作为项目,而数组的值作为第二个项目,它不起作用。

我真的只需要数组,但不知道我应该写什么来得到它。

标签: odatareact-admin

解决方案


我也在为 OData 实现 DataProvider,你需要做的是你必须valuedata对象“包装”你存储的响应数据。

但是数组在valueprop 中,你不能return { data: json };像你一样断言,因为它需要像 {data: [0: {prop1: "hello", prop2: "world"}, 1: { ... }] 这样的对象你返回这个:

{
  "@odata.context":"http://localhost:5001/api/$metadata#apemp",
  "value":[
     {
       "EmpID":1,
       "Abbr":"Admin",
       "BadgeNo":null,
       "ColorRef":0,
       "ContactMethodID":null,
       "DateHired":"2018-05-25T16:42:57-05:00"
     }
  ]
}

所以你需要做的是分配响应json的value prop,例如:

return { data: json.value };

所以它实际上很容易修复


推荐阅读