Index: /trunk/src/org/openstreetmap/josm/io/GeoJSONReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/GeoJSONReader.java	(revision 16932)
+++ /trunk/src/org/openstreetmap/josm/io/GeoJSONReader.java	(revision 16933)
@@ -4,5 +4,11 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.Map;
@@ -52,4 +58,6 @@
     private static final String GEOMETRY = "geometry";
     private static final String TYPE = "type";
+    /** The record separator is 0x1E per RFC 7464 */
+    private static final byte RECORD_SEPARATOR_BYTE = 0x1E;
     private JsonParser parser;
     private Projection projection = Projections.getProjectionByCode("EPSG:4326"); // WGS 84
@@ -351,12 +359,53 @@
     }
 
+    /**
+     * Check if the inputstream follows RFC 7464
+     * @param source The source to check (should be at the beginning)
+     * @return {@code true} if the initial character is {@link GeoJSONReader#RECORD_SEPARATOR_BYTE}.
+     */
+    private static boolean isLineDelimited(InputStream source) {
+        source.mark(2);
+        try {
+            int start = source.read();
+            if (RECORD_SEPARATOR_BYTE == start) {
+                return true;
+            }
+            source.reset();
+        } catch (IOException e) {
+            Logging.error(e);
+        }
+        return false;
+    }
+
     @Override
     protected DataSet doParseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
-        setParser(Json.createParser(source));
+        InputStream markSupported = source.markSupported() ? source : new BufferedInputStream(source);
         ds.setUploadPolicy(UploadPolicy.DISCOURAGED);
-        try {
-            parse();
-        } catch (JsonParsingException e) {
-            throw new IllegalDataException(e);
+        if (isLineDelimited(markSupported)) {
+            BufferedReader reader = new BufferedReader(new InputStreamReader(markSupported));
+            String line = null;
+            String rs = new String(new byte[]{RECORD_SEPARATOR_BYTE}, StandardCharsets.US_ASCII);
+            try {
+                while ((line = reader.readLine()) != null) {
+                    line = line.replaceFirst(rs, "");
+                    try (InputStream is = new ByteArrayInputStream(line.getBytes())) {
+                        setParser(Json.createParser(is));
+                        parse();
+                    } catch (JsonParsingException e) {
+                        throw new IllegalDataException(e);
+                    } finally {
+                        parser.close();
+                    }
+                }
+            } catch (IOException e) {
+                throw new IllegalDataException(e);
+            }
+        } else {
+            setParser(Json.createParser(markSupported));
+            try {
+                parse();
+            } catch (JsonParsingException e) {
+                throw new IllegalDataException(e);
+            }
         }
         return getDataSet();
Index: /trunk/test/data/geoLineByLine.json
===================================================================
--- /trunk/test/data/geoLineByLine.json	(revision 16933)
+++ /trunk/test/data/geoLineByLine.json	(revision 16933)
@@ -0,0 +1,8 @@
+
+{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [102.0, 0.5]}, "properties": {"propA": "valueA"}}]}
+
+{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "LineString", "coordinates": [[102.0, 0.5], [103.0, 1.0], [104.0, 0.0], [105.0, 1.0]]}, "properties": {"propB": "valueB", "propB2": 0.0}}]}
+
+{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "MultiPolygon", "coordinates": [[[[180.0, 40.0], [180.0, 50.0], [170.0, 50.0], [170.0, 40.0], [180.0, 40.0]]], [[[-170.0, 40.0], [-170.0, 50.0], [-180.0, 50.0], [-180.0, 40.0], [-170.0, 40.0]]]]}, "properties": {}}]}
+
+{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Polygon", "coordinates": [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]]]}, "properties": {"propD": "valueD", "propD2": {"this": "that"}, "propD3": true, "propD4": null}}]}
Index: /trunk/test/unit/org/openstreetmap/josm/io/GeoJSONReaderTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/io/GeoJSONReaderTest.java	(revision 16932)
+++ /trunk/test/unit/org/openstreetmap/josm/io/GeoJSONReaderTest.java	(revision 16933)
@@ -6,4 +6,5 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
 import java.io.ByteArrayInputStream;
@@ -13,4 +14,5 @@
 import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
@@ -47,77 +49,97 @@
                 .doParseDataSet(in, null)
                 .getPrimitives(it -> true));
-            assertEquals(20, primitives.size());
 
-            final Node node1 = new Node(new LatLon(0.5, 102.0));
-            final Optional<OsmPrimitive> foundNode1 = primitives.stream()
-                .filter(it -> areEqualNodes(it, node1))
-                .findFirst();
-            assertTrue(foundNode1.isPresent());
-            assertEquals("valueA", foundNode1.get().get("propA"));
+            assertExpectedGeoPrimitives(primitives);
+        }
+    }
 
-            final Way way1 = new Way();
-            way1.addNode(new Node(new LatLon(0.5, 102.0)));
-            way1.addNode(new Node(new LatLon(1, 103)));
-            way1.addNode(new Node(new LatLon(0, 104)));
-            way1.addNode(new Node(new LatLon(1, 105)));
-            final Optional<OsmPrimitive> foundWay1 = primitives.stream()
-                .filter(it -> areEqualWays(it, way1))
-                .findFirst();
-            assertTrue(foundWay1.isPresent());
-            assertEquals("valueB", foundWay1.get().get("propB"));
-            assertEquals("0.0", foundWay1.get().get("propB2"));
-            assertEquals(foundNode1.get(), ((Way) foundWay1.get()).firstNode());
-            assertEquals("valueA", ((Way) foundWay1.get()).firstNode().get("propA"));
+    /**
+     * Tests reading a GeoJSON file that is line by line separated, per RFC 7464
+     * @throws Exception in case of an error
+     */
+    @Test
+    public void testReadLineByLineGeoJSON() throws Exception {
+        try (InputStream in = Files.newInputStream(Paths.get(TestUtils.getTestDataRoot(), "geoLineByLine.json"))) {
+            final List<OsmPrimitive> primitives = new ArrayList<>(new GeoJSONReader()
+                .doParseDataSet(in, null)
+                .getPrimitives(it -> true));
 
-            final Way way2 = new Way();
-            way2.addNode(new Node(new LatLon(40, 180)));
-            way2.addNode(new Node(new LatLon(50, 180)));
-            way2.addNode(new Node(new LatLon(50, 170)));
-            way2.addNode(new Node(new LatLon(40, 170)));
-            way2.addNode(new Node(new LatLon(40, 180)));
-            final Optional<OsmPrimitive> foundWay2 = primitives.stream()
-                .filter(it -> areEqualWays(it, way2))
-                .findFirst();
-            assertTrue(foundWay2.isPresent());
-            assertEquals(
-                ((Way) foundWay2.get()).getNode(0),
-                ((Way) foundWay2.get()).getNode(((Way) foundWay2.get()).getNodesCount() - 1)
-            );
+            assertExpectedGeoPrimitives(primitives);
+        }
+    }
 
-            final Way way3 = new Way();
-            way3.addNode(new Node(new LatLon(40, -170)));
-            way3.addNode(new Node(new LatLon(50, -170)));
-            way3.addNode(new Node(new LatLon(50, -180)));
-            way3.addNode(new Node(new LatLon(40, -180)));
-            way3.addNode(new Node(new LatLon(40, -170)));
-            final Optional<OsmPrimitive> foundWay3 = primitives.stream()
-                .filter(it -> areEqualWays(it, way3))
-                .findFirst();
-            assertTrue(foundWay3.isPresent());
-            assertEquals(
-                ((Way) foundWay3.get()).getNode(0),
-                ((Way) foundWay3.get()).getNode(((Way) foundWay3.get()).getNodesCount() - 1)
-            );
+    private void assertExpectedGeoPrimitives(Collection<OsmPrimitive> primitives) {
+        assertEquals(20, primitives.size());
 
-            final Way way4 = new Way();
-            way4.addNode(new Node(new LatLon(0, 100)));
-            way4.addNode(new Node(new LatLon(0, 101)));
-            way4.addNode(new Node(new LatLon(1, 101)));
-            way4.addNode(new Node(new LatLon(1, 100)));
-            way4.addNode(new Node(new LatLon(0, 100)));
-            final Optional<OsmPrimitive> foundWay4 = primitives.stream()
-                .filter(it -> areEqualWays(it, way4))
-                .findFirst();
-            assertTrue(foundWay4.isPresent());
-            assertEquals(
-                ((Way) foundWay4.get()).getNode(0),
-                ((Way) foundWay4.get()).getNode(((Way) foundWay4.get()).getNodesCount() - 1)
-            );
-            assertEquals("valueD", foundWay4.get().get("propD"));
-            assertFalse(foundWay4.get().hasTag("propD2"));
-            assertEquals("true", foundWay4.get().get("propD3"));
-            assertFalse(foundWay4.get().hasKey("propD4"));
-            assertNull(foundWay4.get().get("propD4"));
-        }
+        final Node node1 = new Node(new LatLon(0.5, 102.0));
+        final Optional<OsmPrimitive> foundNode1 = primitives.stream()
+            .filter(it -> areEqualNodes(it, node1))
+            .findFirst();
+        assertTrue(foundNode1.isPresent());
+        assertEquals("valueA", foundNode1.get().get("propA"));
+
+        final Way way1 = new Way();
+        way1.addNode(new Node(new LatLon(0.5, 102.0)));
+        way1.addNode(new Node(new LatLon(1, 103)));
+        way1.addNode(new Node(new LatLon(0, 104)));
+        way1.addNode(new Node(new LatLon(1, 105)));
+        final Optional<OsmPrimitive> foundWay1 = primitives.stream()
+            .filter(it -> areEqualWays(it, way1))
+            .findFirst();
+        assertTrue(foundWay1.isPresent());
+        assertEquals("valueB", foundWay1.get().get("propB"));
+        assertEquals("0.0", foundWay1.get().get("propB2"));
+        assertEquals(foundNode1.get(), ((Way) foundWay1.get()).firstNode());
+        assertEquals("valueA", ((Way) foundWay1.get()).firstNode().get("propA"));
+
+        final Way way2 = new Way();
+        way2.addNode(new Node(new LatLon(40, 180)));
+        way2.addNode(new Node(new LatLon(50, 180)));
+        way2.addNode(new Node(new LatLon(50, 170)));
+        way2.addNode(new Node(new LatLon(40, 170)));
+        way2.addNode(new Node(new LatLon(40, 180)));
+        final Optional<OsmPrimitive> foundWay2 = primitives.stream()
+            .filter(it -> areEqualWays(it, way2))
+            .findFirst();
+        assertTrue(foundWay2.isPresent());
+        assertEquals(
+            ((Way) foundWay2.get()).getNode(0),
+            ((Way) foundWay2.get()).getNode(((Way) foundWay2.get()).getNodesCount() - 1)
+        );
+
+        final Way way3 = new Way();
+        way3.addNode(new Node(new LatLon(40, -170)));
+        way3.addNode(new Node(new LatLon(50, -170)));
+        way3.addNode(new Node(new LatLon(50, -180)));
+        way3.addNode(new Node(new LatLon(40, -180)));
+        way3.addNode(new Node(new LatLon(40, -170)));
+        final Optional<OsmPrimitive> foundWay3 = primitives.stream()
+            .filter(it -> areEqualWays(it, way3))
+            .findFirst();
+        assertTrue(foundWay3.isPresent());
+        assertEquals(
+            ((Way) foundWay3.get()).getNode(0),
+            ((Way) foundWay3.get()).getNode(((Way) foundWay3.get()).getNodesCount() - 1)
+        );
+
+        final Way way4 = new Way();
+        way4.addNode(new Node(new LatLon(0, 100)));
+        way4.addNode(new Node(new LatLon(0, 101)));
+        way4.addNode(new Node(new LatLon(1, 101)));
+        way4.addNode(new Node(new LatLon(1, 100)));
+        way4.addNode(new Node(new LatLon(0, 100)));
+        final Optional<OsmPrimitive> foundWay4 = primitives.stream()
+            .filter(it -> areEqualWays(it, way4))
+            .findFirst();
+        assertTrue(foundWay4.isPresent());
+        assertEquals(
+            ((Way) foundWay4.get()).getNode(0),
+            ((Way) foundWay4.get()).getNode(((Way) foundWay4.get()).getNodesCount() - 1)
+        );
+        assertEquals("valueD", foundWay4.get().get("propD"));
+        assertFalse(foundWay4.get().hasTag("propD2"));
+        assertEquals("true", foundWay4.get().get("propD3"));
+        assertFalse(foundWay4.get().hasKey("propD4"));
+        assertNull(foundWay4.get().get("propD4"));
     }
 
@@ -140,9 +162,8 @@
     /**
      * Test reading a JSON file which is not a proper GeoJSON (type missing).
-     * @throws IllegalDataException always
      */
-    @Test(expected = IllegalDataException.class)
-    public void testReadGeoJsonWithoutType() throws IllegalDataException {
-        new GeoJSONReader().doParseDataSet(new ByteArrayInputStream("{}".getBytes(StandardCharsets.UTF_8)), null);
+    public void testReadGeoJsonWithoutType() {
+        assertThrows(IllegalDataException.class, () ->
+                new GeoJSONReader().doParseDataSet(new ByteArrayInputStream("{}".getBytes(StandardCharsets.UTF_8)), null));
     }
 
