处理来自API的JSON中的语法错误

Unk*_*per 1 javascript json jsonp angularjs angular-promise

想象一下JSON(, instead of :)中的以下语法错误:

[
    {
        "name": "anna",
        "email": "anna@gmail.com",
        "town", "london"
    },
...
]
Run Code Online (Sandbox Code Playgroud)

我想知道是否有可能处理此错误而不是获取异常,获取错误的对象,更正错误并继续使用正确的版本.

这是我的Angular服务的一部分; 我试图获取文本而不是JSON数据,但它不起作用......

 angular.module('mine', [])
    .config(function($sceProvider) {
        // Completely disable SCE.  
        $sceProvider.enabled(false);
    })
    .config(['$sceDelegateProvider', function($sceDelegateProvider) {
        $sceDelegateProvider.resourceUrlWhitelist([
        'self',
        'http://www.mocky.io/v2/5807df4a10000004122b74e2'
        ]);
    }])
  .config(function ($httpProvider) {
        $httpProvider.interceptors.push(function($q) {
            return {
                'request': function(config) {
                    config.headers.Accept = 'text/plain';
                    return config;
                },
                'response': function(response) {
                    try {
                        // try to parse it
                        response.data = JSON.parse(response.data);  
                    } catch (ex) {
                        // try to fix it
                        console.log("error " + ex);
                        console.log(response.data);
                        response.data = {fixed_data : "data"};
                    }
                    // return the corect data.
                    // note that the original response.data WILL BE CHANGED and this is expected.
                    return response;
                }
            };
        });
  })



       angular.module('mine').factory('MyFactory', ['$http','$q',  function MyFactory($http,$q) {
        return {
            getData: function() {    
                var deferred = $q.defer(),
                config = {
                        params: { }
                    },

                url="http://www.mocky.io/v2/5807df4a10000004122b74e2";          

                $http.jsonp(url,config)
                .then(              
                    function (response) {
                        deferred.resolve(response.data);
                    },  
                    function (error) {
                        console.log(error);
                        return $q.reject('Error retrieving data');
                    }
                );

                return deferred.promise;
            }
        };
 }]);
Run Code Online (Sandbox Code Playgroud)

无论如何将上述承诺引入成功回调,检索错误的JSON并进行纠正?我怎么可以根据上面的例子编写代码呢?

或者更容易一些,如何检索文本而不是JSON数据,$http.jsonp以免被驱动到失败回调?

It-*_*t-Z 7

TL; DR

在进一步了解OP问题后编辑:

在您想要编辑响应内容的一般情况下,您可以使用"拦截器"进行编辑,但响应应该是合法的.也就是说,如果你想在一个正确的JSON中将数字字符串更改为整数 - 那么这是可能的.

在这种情况下,OP在JSON格式不正确的情况下正在升级 - 这是不可能的!

长话故事

第一

进入经典的XY问题!

您应该问自己为什么JSON会被破坏而不会尝试在客户端代码中修复它.想一想 - 如果你现在修复它,你只会遇到更多的问题,后来有人会修复这个问题 - 那么将会遇到破解的代码.

如果JSON应该是:

[
    {
        "name": "anna",
        "email": "anna@gmail.com",
        "addresses": [{"town": "london", ...}, ...]
    },
...
]
Run Code Online (Sandbox Code Playgroud)

或者(上帝保佑):

[
    {
        "name": "anna",
        "email": ["anna@gmail.com","town", "london"]
    },
...
]
Run Code Online (Sandbox Code Playgroud)

你知道 - 我的观点是 - API被破坏了,它可以是任何东西.你应该修复API.如果此API不是您的修复 - >使用其他API或联系所有者来修复它.

JSONP

JSONP是一种让API直接调用代码的方法.您必须信任此API.如果API会给我错误的JSON - 我会离开!

简而言之,JSONP在Angular中(或实际上在任何地方)的工作方式是通过将<script>标记注入到DOM中并src指向JSONp请求的URL.

服务器将使用函数名称填充 JSON数据(最常见callback但它可以是任何全局可访问的函数(Angular正在使用angular.callbacks._xyz)并将发送它.

然后浏览器调用从中下载的脚本src.

现在,问题在于它是调用脚本的浏览器.它不在Angular的手中.而正是OP正面临的问题-脚本必须以正确的JavaScript进行评估,以开始与浏览器是这样做的,没有棱角.这是必须的.你无法进​​入它的中间.如果你这样做,可能会带来安全风险.这就是为什么,例如,JSONP请求的响应将始终(按照惯例...)返回MIME类型,application/javascript无论您要求什么.

战争 - 这里是龙!

我劝你不要走这条路!

如果你坚持要从JSONP调用一个带有错误的JSON(并且错误,我的意思是JSON可以被解析为对象,但是你想要在该对象中改变某些东西)你可以尝试添加" 拦截器 "

.config(function ($httpProvider) {
    $httpProvider.interceptors.push(function($q) {
        return {
            'request': function(config) {
                // here you can edit the request.
                return config;
            },
            'response': function(response) {
                // response.data will hold your bad data
                // you could edit it
                response.data = fix(response.data);
                // return the correct data.
                return response;
            }
        };
    });
})
Run Code Online (Sandbox Code Playgroud)

请注意,您还可以覆盖默认转换

另外,请务必:

   // Whitelist the JSONP endpoint that we are using to show that we trust it
  .config(['$sceDelegateProvider', function($sceDelegateProvider) {
    $sceDelegateProvider.resourceUrlWhitelist([
      'self',
      'https://your.api.url/**'
    ]);
  }])
Run Code Online (Sandbox Code Playgroud)

如果一切顺利,你可以致电:

//uncomment {jsonpCallbackParam: 'callback'} if your jsonp callback
//parameter at the backend uses some other name but the default 'callback'
$http.jsonp(https://your.api.url/*,{jsonpCallbackParam: 'callback'}*/)
.then(function(response) {
    $scope.status = response.status;
    $scope.data = response.data;
  }, function(response) {
    $scope.data = response.data || 'Request failed';
    $scope.status = response.status;
});
Run Code Online (Sandbox Code Playgroud)

  • 我很抱歉你这么认为. (3认同)