FF 13,IE 9:JSON stringify / geolocation对象

时间:2012-06-14 22:26:36

标签: javascript json firefox geolocation internet-explorer-9

我试图让Firefox 13将地理定位位置对象转换为JSON字符串,但它返回一个空字符串而不是我的JSON对象的正确字符串表示形式。这在最新版本的Chrome和Safari以及Android浏览器中运行良好。这是我的代码:

if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition( 
        function (position) {  
            //Success handler
            console.log(position); //This outputs the position object to the console
            var gps = JSON.stringify(position); 
            console.log(gps); //This outputs an empty string!
        }, 
        function (error)
        {   
            //Handle error
        },
        { maximumAge: 3000, timeout: 60000, enableHighAccuracy: true }
        );
}
else {
    //Handle error
}

在Chrome中,这会输出一个地理位置对象,以及此字符串:

"{"coords":{"latitude":XYZ,"heading":null,"accuracy":40,"altitudeAccuracy":null,"altitude":null,"longitude":XYZ,"speed":null},"timestamp":1339712284200}"

但是,在Firefox 13中,输出只是一个空字符串,即使打印到控制台的地理定位对象的所有意图和目的都与Chrome显示的对象相同。关于这里出了什么问题的任何想法? This似乎是一个相关问题,但我也没有在那里找到解决方案。顺便说一句,IE9显示相同的行为。

5 个答案:

答案 0 :(得分:18)

我创建了一个克隆函数,将Geolocation位置(或任何其他)对象克隆到一个对象中,该对象将按预期进行字符串化:

function cloneAsObject(obj) {
    if (obj === null || !(obj instanceof Object)) {
        return obj;
    }
    var temp = (obj instanceof Array) ? [] : {};
    // ReSharper disable once MissingHasOwnPropertyInForeach
    for (var key in obj) {
        temp[key] = cloneAsObject(obj[key]);
    }
    return temp;
}

注意: 可能不支持地理位置类型中未使用的类型(例如日期)

然后您将在代码中使用它:

var gps = JSON.stringify(cloneAsObject(position)); 

希望这有助于某人:)

答案 1 :(得分:6)

正在发生的事情是JSON.stringify默认只查看对象自己的属性。

根据DOM规范,所有DOM属性实际上都存在于对象的原型中。

IE和Firefox通过将属性放在原型上来正确实现规范。 Chrome和Safari不会:他们将属性直接放在对象上。这使得这个案例起作用,但打破了其他事情(例如挂钩属性getter和setter的能力)....

有人谈到将JSON方法添加到某些DOM对象中,以便为JSON.stringify提供更合理的行为。

答案 2 :(得分:1)

我能找到的最简单的方法是使用Lodash

lodash.defaultsDeep({coords: {}}, p)

先安装npm i lodash.defaultsdeep,然后

import defaultsDeep from 'lodash.defaultsdeep'; 
//const defaultsDeep = require('lodash.defaultsdeep'); //CommonJS/Node


JSON.stringify(defaultsDeep({coords: {}}, p))

//Outputs:
// "{
//   "coords": {
//     "latitude": 55.6300000,
//     "longitude": -6.1520000,
//     "altitude": null,
//     "accuracy": 1794,
//     "altitudeAccuracy": null,
//     "heading": null,
//     "speed": null
//   },
//   "timestamp": 1601361646336
// }"

答案 3 :(得分:0)

一个老问题,但我来到这里是因为stringify也不适合我。

在搜索了所有克隆功能之后,我采取了另一种方法。

export async function getLocation(): Promise<Position> {
    return new Promise((resolve, reject) => {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition((position: Position) =>
                resolve({
                    coords: {
                        accuracy: position.coords.accuracy,
                        altitude: position.coords.altitude,
                        altitudeAccuracy: position.coords.altitudeAccuracy,
                        heading: position.coords.heading,
                        latitude: position.coords.latitude,
                        longitude: position.coords.longitude,
                        speed: position.coords.speed,
                    },
                    timestamp: position.timestamp,
                }),
            );
        } else {
            reject(new Error('Browser does not support geolocation!'));
        }
    });
}

getLocation返回一个“可字符串化”的Position对象!

答案 4 :(得分:0)

只是迈克回答的更新:

export function getUserPosition(): Promise<GeolocationPosition> {
  return new Promise((resolve, reject) => {
    if (navigator.geolocation) {
      navigator.geolocation.getCurrentPosition(
        (position: GeolocationPosition) =>
          resolve({
            coords: {
              accuracy: position.coords.accuracy,
              altitude: position.coords.altitude,
              altitudeAccuracy: position.coords.altitudeAccuracy,
              heading: position.coords.heading,
              latitude: position.coords.latitude,
              longitude: position.coords.longitude,
              speed: position.coords.speed,
            },
            timestamp: position.timestamp,
          }),
        (err) => {
          reject(err);
        },
        {
          timeout: GET_CURRENT_POSITION_TIMEOUT,
          maximumAge: GET_CURRENT_POSITION_MAX_AGE,
          /* 
          There was an issue with location in Chrome 89 if this wasn't set to `false`,
          so the best solution is set it to false in dev & test and undefine it in production
          */
          enableHighAccuracy:
            process.env.NODE_ENV !== 'production' ? false : undefined,
        }
      );
    } else {
      reject(new Error('Browser does not support geolocation!'));
    }
  });
}