diff --git a/src/ol/parser/geojson.exports b/src/ol/parser/geojson.exports
index d7ec119aa5..7143cfbf11 100644
--- a/src/ol/parser/geojson.exports
+++ b/src/ol/parser/geojson.exports
@@ -1,3 +1,6 @@
@exportSymbol ol.parser.GeoJSON
@exportProperty ol.parser.GeoJSON.prototype.read
+@exportProperty ol.parser.GeoJSON.read
+@exportProperty ol.parser.GeoJSON.prototype.write
+@exportProperty ol.parser.GeoJSON.write
diff --git a/src/ol/parser/geojson.js b/src/ol/parser/geojson.js
index 83f711205e..ca55c5b923 100644
--- a/src/ol/parser/geojson.js
+++ b/src/ol/parser/geojson.js
@@ -1,8 +1,10 @@
goog.provide('ol.parser.GeoJSON');
goog.require('goog.asserts');
+goog.require('goog.object');
goog.require('ol.Feature');
goog.require('ol.geom.Geometry');
+goog.require('ol.geom.GeometryCollection');
goog.require('ol.geom.GeometryType');
goog.require('ol.geom.LineString');
goog.require('ol.geom.MultiLineString');
@@ -24,6 +26,7 @@ goog.require('ol.parser.StringFeatureParser');
*/
ol.parser.GeoJSON = function() {};
goog.inherits(ol.parser.GeoJSON, ol.parser.Parser);
+goog.addSingletonGetter(ol.parser.GeoJSON);
/**
@@ -39,6 +42,18 @@ ol.parser.GeoJSON.prototype.read = function(str) {
};
+/**
+ * Parse a GeoJSON string.
+ * @param {string} str GeoJSON string.
+ * @return {ol.Feature|Array.
|
+ * ol.geom.Geometry|Array.} Parsed geometry or array
+ * of geometries.
+ */
+ol.parser.GeoJSON.read = function(str) {
+ return ol.parser.GeoJSON.getInstance().read(str);
+};
+
+
/**
* Parse a GeoJSON feature collection.
* @param {string} str GeoJSON feature collection.
@@ -272,6 +287,124 @@ ol.parser.GeoJSON.prototype.parsePolygon_ = function(json, opt_vertices) {
};
+/**
+ * @param {ol.geom.Geometry} geometry Geometry to encode.
+ * @return {GeoJSONGeometry} GeoJSON geometry.
+ * @private
+ */
+ol.parser.GeoJSON.prototype.encodeGeometry_ = function(geometry) {
+ var type = geometry.getType();
+ return /** @type {GeoJSONGeometry} */({
+ type: goog.object.findKey(ol.parser.GeoJSON.GeometryType,
+ function(value, key) {
+ return value === type;
+ }
+ ),
+ coordinates: geometry.getCoordinates()
+ });
+};
+
+
+/**
+ * @param {ol.geom.GeometryCollection} collection Geometry collection to
+ * encode.
+ * @return {GeoJSONGeometryCollection} GeoJSON geometry collection.
+ * @private
+ */
+ol.parser.GeoJSON.prototype.encodeGeometryCollection_ = function(collection) {
+ var geometries = [];
+ for (var i = 0, ii = collection.components.length; i < ii; ++i) {
+ geometries.push(this.encodeGeometry_(collection.components[i]));
+ }
+ return /** @type {GeoJSONGeometryCollection} */({
+ type: 'GeometryCollection',
+ geometries: geometries
+ });
+};
+
+
+/**
+ * @param {Array.} collection Feature collection to encode.
+ * @return {GeoJSONFeatureCollection} GeoJSON feature collection.
+ * @private
+ */
+ol.parser.GeoJSON.prototype.encodeFeatureCollection_ = function(collection) {
+ var features = [];
+ for (var i = 0, ii = collection.length; i < ii; ++i) {
+ features.push(this.encodeFeature_(collection[i]));
+ }
+ return /** @type {GeoJSONFeatureCollection} */({
+ type: 'FeatureCollection',
+ features: features
+ });
+};
+
+
+/**
+ * @param {ol.Feature} feature Feature to encode.
+ * @return {GeoJSONFeature} GeoJSON feature.
+ * @private
+ */
+ol.parser.GeoJSON.prototype.encodeFeature_ = function(feature) {
+ var geometry = feature.getGeometry(),
+ attributes = feature.getAttributes();
+ var properties = goog.object.filter(attributes,
+ function(element, index, array) {
+ return !(element instanceof ol.geom.Geometry);
+ });
+ return /** @type {GeoJSONFeature} */({
+ type: 'Feature',
+ properties: properties,
+ geometry: this.encodeGeometry_(geometry)
+ });
+};
+
+
+/**
+ * @param {ol.geom.GeometryCollection|ol.geom.Geometry|Array.|
+ * ol.Feature} obj The object to encode.
+ * @return {string} The GeoJSON as string.
+ * @private
+ */
+ol.parser.GeoJSON.prototype.encode_ = function(obj) {
+ var result;
+ if (obj instanceof ol.geom.GeometryCollection) {
+ result = this.encodeGeometryCollection_(obj);
+ } else if (obj instanceof ol.geom.Geometry) {
+ result = this.encodeGeometry_(obj);
+ } else if (obj instanceof ol.Feature) {
+ result = this.encodeFeature_(obj);
+ } else if (goog.isArray(obj)) {
+ result = this.encodeFeatureCollection_(obj);
+ }
+ return JSON.stringify(result);
+};
+
+
+/**
+ * Write out a geometry, geometry collection, feature or an array of features
+ * as a GeoJSON string.
+ * @param {ol.geom.Geometry|ol.geom.GeometryCollection|ol.Feature|
+ * Array.} obj The object to encode.
+ * @return {string} GeoJSON for the geometry.
+ */
+ol.parser.GeoJSON.write = function(obj) {
+ return ol.parser.GeoJSON.getInstance().write(obj);
+};
+
+
+/**
+ * Write out a geometry, geometry collection, feature or an array of features
+ * as a GeoJSON string.
+ * @param {ol.geom.Geometry|ol.geom.GeometryCollection|ol.Feature|
+ * Array.} obj The object to encode.
+ * @return {string} GeoJSON for the geometry.
+ */
+ol.parser.GeoJSON.prototype.write = function(obj) {
+ return this.encode_(obj);
+};
+
+
/**
* @enum {ol.geom.GeometryType}
*/
diff --git a/test/spec/ol/parser/geojson.test.js b/test/spec/ol/parser/geojson.test.js
index 053370ad2d..0d08cbdbda 100644
--- a/test/spec/ol/parser/geojson.test.js
+++ b/test/spec/ol/parser/geojson.test.js
@@ -68,6 +68,53 @@ describe('ol.parser.GeoJSON', function() {
]
};
+ describe('#write()', function() {
+
+ it('encodes point', function() {
+ var point = new ol.geom.Point([10, 20]);
+ var geojson = parser.write(point);
+ expect(point).to.eql(parser.read(geojson));
+ });
+
+ it('encodes linestring', function() {
+ var linestring = new ol.geom.LineString([[10, 20], [30, 40]]);
+ var geojson = parser.write(linestring);
+ expect(linestring).to.eql(parser.read(geojson));
+ });
+
+ it('encodes polygon', function() {
+ var outer = [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]],
+ inner1 = [[1, 1], [2, 1], [2, 2], [1, 2], [1, 1]],
+ inner2 = [[8, 8], [9, 8], [9, 9], [8, 9], [8, 8]];
+ var polygon = new ol.geom.Polygon([outer, inner1, inner2]);
+ var geojson = parser.write(polygon);
+ expect(polygon).to.eql(parser.read(geojson));
+ });
+
+ it('encodes geometry collection', function() {
+ var collection = new ol.geom.GeometryCollection([
+ new ol.geom.Point([10, 20]),
+ new ol.geom.LineString([[30, 40], [50, 60]])
+ ]);
+ var geojson = parser.write(collection);
+ // surprised to see read return an Array of geometries instead of
+ // a true ol.geom.GeometryCollection, so compare collection.components
+ expect(collection.components).to.eql(parser.read(geojson));
+ });
+
+ it('encodes feature collection', function() {
+ var str = JSON.stringify(data),
+ array = parser.read(str);
+ var geojson = parser.write(array);
+ var result = parser.read(geojson);
+ for (var i = 0, ii = array.length; i < ii; ++i) {
+ expect(array[i].getGeometry()).to.eql(result[i].getGeometry());
+ expect(array[i].getAttributes()).to.eql(result[i].getAttributes());
+ }
+ });
+
+ });
+
describe('#read()', function() {
it('parses point', function() {
@@ -221,6 +268,7 @@ describe('ol.parser.GeoJSON', function() {
goog.require('ol.Feature');
goog.require('ol.extent');
+goog.require('ol.geom.GeometryCollection');
goog.require('ol.geom.LinearRing');
goog.require('ol.geom.LineString');
goog.require('ol.geom.Point');