Index: src/org/openstreetmap/josm/io/GeoJSONWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/GeoJSONWriter.java	(revision 15161)
+++ src/org/openstreetmap/josm/io/GeoJSONWriter.java	(working copy)
@@ -4,11 +4,14 @@
 import java.io.StringWriter;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.stream.Stream;
 
 import javax.json.Json;
@@ -47,6 +50,7 @@
     private final DataSet data;
     private final Projection projection;
     private static final BooleanProperty SKIP_EMPTY_NODES = new BooleanProperty("geojson.export.skip-empty-nodes", true);
+    private static final Set<Way> processedMultipolygonWays = new HashSet<>();
 
     /**
      * Constructs a new {@code GeoJSONWriter}.
@@ -108,13 +112,17 @@
         public void visit(Way w) {
             if (w != null) {
                 final JsonArrayBuilder array = getCoorsArray(w.getNodes());
-                if (w.isClosed() && ElemStyles.hasAreaElemStyle(w, false)) {
-                    final JsonArrayBuilder container = Json.createArrayBuilder().add(array);
-                    geomObj.add("type", "Polygon");
-                    geomObj.add("coordinates", container);
+                if (w.isClosed()) {
+                    if (ElemStyles.hasAreaElemStyle(w, false) || !processedMultipolygonWays.contains(w)) {
+                        final JsonArrayBuilder container = Json.createArrayBuilder().add(array);
+                        geomObj.add("type", "Polygon");
+                        geomObj.add("coordinates", container);
+                    }
                 } else {
-                    geomObj.add("type", "LineString");
-                    geomObj.add("coordinates", array);
+                    if (w.isTagged() || !processedMultipolygonWays.contains(w)) {
+                        geomObj.add("type", "LineString");
+                        geomObj.add("coordinates", array);
+                    }
                 }
             }
         }
@@ -135,11 +143,23 @@
                 geomObj.add("type", "MultiPolygon");
                 final JsonArrayBuilder multiPolygon = Json.createArrayBuilder().add(polygon);
                 geomObj.add("coordinates", multiPolygon);
+                processedMultipolygonWays.addAll(r.getMemberPrimitives(Way.class));
             } catch (MultipolygonBuilder.JoinedPolygonCreationException ex) {
                 Logging.warn("GeoJSON: Failed to export multipolygon {0}", r.getUniqueId());
                 Logging.warn(ex);
             }
         }
+
+        private JsonArrayBuilder getCoorsArray(Iterable<Node> nodes) {
+            final JsonArrayBuilder builder = Json.createArrayBuilder();
+            for (Node n : nodes) {
+                LatLon ll = n.getCoor();
+                if (ll != null) {
+                    builder.add(getCoorArray(null, ll));
+                }
+            }
+            return builder;
+        }
     }
 
     private JsonArrayBuilder getCoorArray(JsonArrayBuilder builder, LatLon c) {
@@ -152,17 +172,6 @@
                 .add(BigDecimal.valueOf(c.getY()).setScale(11, RoundingMode.HALF_UP));
     }
 
-    private JsonArrayBuilder getCoorsArray(Iterable<Node> nodes) {
-        final JsonArrayBuilder builder = Json.createArrayBuilder();
-        for (Node n : nodes) {
-            LatLon ll = n.getCoor();
-            if (ll != null) {
-                builder.add(getCoorArray(null, ll));
-            }
-        }
-        return builder;
-    }
-
     protected void appendPrimitive(OsmPrimitive p, JsonArrayBuilder array) {
         if (p.isIncomplete() ||
             (SKIP_EMPTY_NODES.get() && p instanceof Node && p.getKeys().isEmpty())) {
@@ -181,11 +190,13 @@
         p.accept(new GeometryPrimitiveVisitor(geomObj));
         final JsonObject geom = geomObj.build();
 
-        // Build primitive JSON object
-        array.add(Json.createObjectBuilder()
-                .add("type", "Feature")
-                .add("properties", prop.isEmpty() ? JsonValue.NULL : prop)
-                .add("geometry", geom.isEmpty() ? JsonValue.NULL : geom));
+        if (!geom.isEmpty()) {
+            // Build primitive JSON object
+            array.add(Json.createObjectBuilder()
+                    .add("type", "Feature")
+                    .add("properties", prop.isEmpty() ? JsonValue.NULL : prop)
+                    .add("geometry", geom.isEmpty() ? JsonValue.NULL : geom));
+        }
     }
 
     protected void appendLayerBounds(DataSet ds, JsonObjectBuilder object) {
@@ -213,7 +224,18 @@
     protected void appendLayerFeatures(DataSet ds, JsonObjectBuilder object) {
         JsonArrayBuilder array = Json.createArrayBuilder();
         if (ds != null) {
-            ds.allNonDeletedPrimitives().forEach(p -> appendPrimitive(p, array));
+            processedMultipolygonWays.clear();
+            Collection<OsmPrimitive> primitives = ds.allNonDeletedPrimitives();
+            // Relations first
+            for (OsmPrimitive p : primitives) {
+                if (p instanceof Relation)
+                    appendPrimitive(p, array);
+            }
+            for (OsmPrimitive p : primitives) {
+                if (!(p instanceof Relation))
+                    appendPrimitive(p, array);
+            }
+            processedMultipolygonWays.clear();
         }
         object.add("features", array);
     }
