我试图让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显示相同的行为。
答案 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!'));
}
});
}