为什么JSON.parse()无法按预期运行

时间:2018-12-11 11:05:28

标签: javascript json

此代码怎么可能:

this.store.select(getAuthResponseSelector)
        .subscribe((response: AuthenticateResponse) => {
            if (response != null) {
                console.log('Response', response);
                console.log('ResponseType', typeof response);
                console.log('EntroSubscribeTokenBefore', JSON.parse(JSON.stringify(response)));
                console.log('EntroSubscribeTokenType', typeof JSON.parse(JSON.stringify(response)));
                console.log('EntroSubscribeToken', JSON.parse(JSON.stringify(response)).access_token);
                const newToken = Object.assign({}, response);
                console.log('NewObject', typeof newToken);
                for(let key in newToken){
                    console.log('Key:', newToken[key])
                }
                this.token = newToken.access_token
            }
        });

打印此输出:

[12:32:39]  console.log: Response
            {"access_token":"afcddc76-8322-4186-9b54-aa4143f381eb","token_type":"bearer","refresh_token":"fda3fcf4-8335-45cf-94ca-cd0aec1a90cb","expires_in":26313,"scope":"custom
            default","firstname":"testswinetmm_cost","lastname":"testswinetmm_cost","email":"testswinetmm_cost@testingmail.com","uid":"testswinetmm_cost"}
[12:32:39]  console.log: ResponseType string
[12:32:39]  console.log: EntroSubscribeTokenBefore
            {"access_token":"afcddc76-8322-4186-9b54-aa4143f381eb","token_type":"bearer","refresh_token":"fda3fcf4-8335-45cf-94ca-cd0aec1a90cb","expires_in":26313,"scope":"custom
            default","firstname":"testswinetmm_cost","lastname":"testswinetmm_cost","email":"testswinetmm_cost@testingmail.com","uid":"testswinetmm_cost"}
[12:32:39]  console.log: EntroSubscribeTokenType string
[12:32:39]  console.log: EntroSubscribeToken
[12:32:39]  console.log: NewObject object
[12:32:39]  console.log: Key: {
[12:32:39]  console.log: Key: "
[12:32:39]  console.log: Key: a
[12:32:39]  console.log: Key: c
[12:32:39]  console.log: Key: c
[12:32:39]  console.log: Key: e
[12:32:39]  console.log: Key: s
[12:32:39]  console.log: Key: s
[12:32:39]  console.log: Key: _
[12:32:39]  console.log: Key: t
[12:32:39]  console.log: Key: o
[12:32:39]  console.log: Key: k
[12:32:39]  console.log: Key: e
[12:32:39]  console.log: Key: n
[12:32:39]  console.log: Key: "
[12:32:39]  console.log: Key: :
[12:32:39]  console.log: Key: "
[12:32:39]  console.log: Key: a
[12:32:39]  console.log: Key: f
[12:32:39]  console.log: Key: c
[12:32:39]  console.log: Key: d
[12:32:39]  console.log: Key: d
...

响应对象具有自定义类型(无论如何都是对象),但是尝试将其转换为JSON对象,我得到此结果,有人可以解释一下这怎么可能吗?

更新

即使在对字符串进行字符串化时也可能会出错。当我用Object.asssign()创建一个新对象的最后一部分时,我会打印类型并告诉我它是一个对象,但是当迭代其属性时,它会将每个字母打印为String,我认为这应该不会发生

更新2 我也知道在这种情况下JSON.parse(JSON.stringify())没有意义,我已经尝试过,因为基于我期望的响应以及我真正收到的响应没有意义,这就是为什么我尝试各种转换

P.D:JSON.parse(JSON.stringify())并不奇怪,通常用于创建JSON对象的深层副本:)

4 个答案:

答案 0 :(得分:3)

这一定是因为您的response是字符串而不是对象。因此,JSON.stringify从字符串创建JSON字符串,然后JSON.parse将该JSON字符串解析为普通字符串。

编辑:

您知道即使您在TypeScript中使用response: AuthenticateResponseresponse可能也不是该类型吗?您的response是包含JSON的字符串的简洁类型。

答案 1 :(得分:1)

看来response是一个字符串,因此您需要先使用JSON.parse()对其进行解析,然后才能正确使用它。现在发生的是,您正在遍历字符串,并且遍历字符串将打印出该字符串中的每个字符。

我怀疑这样的事情是您真正想要发生的事情(请注意,在这种情况下,使用JSON.parse()以及Object.assign()都是多余的)

var response = '{"access_token":"afcddc76-8322-4186-9b54-aa4143f381eb","token_type":"bearer","refresh_token":"fda3fcf4-8335-45cf-94ca-cd0aec1a90cb","expires_in":29605,"scope":"custom default","firstname":"testswinetmm_cost","lastname":"testswinetmm_cost","email":"testswinetmm_cost@testingmail.com","uid":"testswinetmm_cost"}';
const newToken = JSON.parse(response);

for(let key in newToken){
   console.log(key, ":", newToken[key])
}


P.S。在您的控制台中。日志JSON.parse(JSON.stringify(response))毫无意义。 -如果这样做,您将得到的内容完全正确,因为解析与字符串化是完全相反的-仅当有要转换为对象的字符串时才需要parse(),并且只需要stringify()如果​​您有一个对象想要转换为字符串。您永远不会同时需要两者。可能这加剧了您的困惑,但不清楚。

答案 2 :(得分:0)

console.log('EntroSubscribeTokenType', typeof JSON.parse(JSON.stringify(response)));
  

[11:37:46] console.log:EntroSubscribeTokenType字符串

这意味着response实际上是一个字符串。

const json = '{ "name" : "Fred" }';
console.log(typeof json, json);

const jsonToString = JSON.stringify(json);
console.log(typeof jsonToString, jsonToString);

const jsonToStringParsed = JSON.parse(jsonToString);
console.log(typeof jsonToStringParsed, jsonToStringParsed);

console.log("json === jsonToStringParsed", json === jsonToStringParsed);

因此,当您尝试创建新对象时涉及到零件时,实际上是在使用 string 。因此,Object.assign会给您带来您可能不会想到的东西:

const response = '{ "name" : "Fred" }';

const newToken = Object.assign({}, response);

console.log(typeof newToken);
console.log(newToken);

它实际上是字符串中的一个新对象,因此键值对是索引以及与之相关的字符。这是因为将字符串原语转换为字符串 object 进行复制

const stringObject = new String( '{ "name" : "Fred" }');

console.log("typeof stringObject:", typeof stringObject);
console.log("stringObject instanceof String:", stringObject instanceof String);
console.log(stringObject);

因此,当您遍历newToken时,它是String的String对象表示形式的对象表示形式。

const response = '{ "name" : "Fred" }';

const newToken = Object.assign({}, response);

for (let key in newToken) {
  console.log("key -> valye:", key, newToken[key])
}

最后一点,Object.assign()不会创建String对象的新副本-实际上,您会得到一个普通对象,因为原型没有被复制到

const string = '{ "name" : "Fred" }';
const stringObject = new String(string);

const newTokenFromString = Object.assign({}, string);
const newTokenFromStringObject = Object.assign({}, stringObject);

//false - because it's a string primitive
console.log("string instanceof String:", string instanceof String);
//true
console.log("stringObject instanceof String:", stringObject instanceof String);
//false - it's an object, not an instance of String
console.log("newTokenFromString instanceof String:", newTokenFromString instanceof String);
//false - it's an object, not an instance of String
console.log("newTokenFromStringObject instanceof String:", newTokenFromStringObject instanceof String);

答案 3 :(得分:-4)

您正在以对象格式获得响应。要检查JSON数据的语法是否有效,您可以将响应文本复制到JSON Formatter之类的在线JSON解析器中。