17

我试图让 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 显示的对象相同。关于这里出了什么问题的任何想法?似乎是一个相关的问题,但我也没有看到解决方案。顺便说一句,IE9 显示相同的行为。

4

5 回答 5

29

我创建了一个克隆函数来将 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;
}

注意: 可能不支持 Geoposition 类型中未使用的类型(例如 Date)

然后,您将在代码中按如下方式使用它:

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

希望这可以帮助某人:)

于 2016-06-09T12:56:49.163 回答
12

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

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

IE 和 Firefox 通过将属性放在原型上来正确实现规范。Chrome 和 Safari 没有:它们将属性直接放在对象上。这使得这个案例有效,但破坏了其他东西(例如,挂钩属性 getter 和 setter 的能力)......

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

于 2012-06-15T05:17:54.347 回答
3

老问题,但我来到这里是因为 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返回一个“可字符串化”的位置对象!

于 2019-12-13T11:20:32.133 回答
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
// }"
于 2020-09-29T07:06:13.100 回答
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!'));
    }
  });
}
于 2021-06-09T10:14:04.170 回答