Giter VIP home page Giter VIP logo

geojsonhint's Introduction

This repo has been archived. You can use @placemarkio/check-geojson instead.

Build Status Coverage Status

geojsonhint: complete, fast, standards-based validation for geojson

Important: development of geojsonhint is currently paused. Until development restarts, please refrain from adding non-critical issues or PRs.

A lint tool for the GeoJSON standard. geojsonhint is written to the standard, with no missing or additional opinions about structure.

Thanks to jsonlint-lines, GeoJSON that is also not valid JSON can return informative, line-oriented parsing errors.

Specification

The basis of this tool is the published GeoJSON specification.

API

errors = geojsonhint.hint(string or object, options)

Lint a file, given as a string or object. This call detects all aberrations from the GeoJSON standards and returns them as an array of errors. An example of the output:

[{
  "message": "\"features\" property should be an array, but is an object instead",
  "line": 1
}]

The options argument is optional. It has these options:

noDuplicateMembers.

By default, geojsonhint will treat repeated properties as an error: you can set noDuplicateMembers to false to allow them. For instance:

geojsonhint.hint('{"type":"invalid","type":"Feature","properties":{},"geometry":null}', {
    noDuplicateMembers: false
});

The repeated type property in this input will be ignored with the option, and flagged without it.

precisionWarning.

GeoJSON now recommends six decimal places of accuracy for coordinates (Section 11.2). This option adds a warning message when coordinates contain over 6 decimal places of accuracy, up to 10 coordinates before the warning message is truncated for performance.

geojsonhint.hint('{ "type": "Point", "coordinates": [100.0000000001, 5.0000000001] }', {
    precisionWarning: false
});

With this option enabled, geojsonhint will produce these warnings:

[{
  line: 1,
  level: 'message',
  message: 'precision of coordinates should be reduced'
}, {
  line: 1,
  level: 'message',
  message: 'precision of coordinates should be reduced'
}]

Without this option, this input will pass without errors.

ignoreRightHandRule.

GeoJSON specification defined that linear rings must follow right-hand rule, but also says that for backward compatibility reasons parsers should not rejects polygons wiht incorrect winding order. For that kind of situations geojsonhint has an option ignoreRightHandRule which is false by default. Setting this option to true will cause geojsonhint to skip right-hand rule validation.

geojsonhint.hint(geojsonWithIncorrectWindingOrder, {
  ignoreRightHandRule: true
});

with this option enabled, geojsonhint will not validate winding order.

Line Numbers

Note that the GeoJSON can be given as a string or as an object. Here's how to choose which input to use:

  • string inputs receive line numbers for each error. These make errors easier to track down if the GeoJSON is hand-written.
  • object inputs don't have line numbers but are evaluated faster, by up to 10x. GeoJSONHint is very fast already so unless you have identified it as a bottleneck in your application, don't prematurely optimize based on this fact.

If you're really trying to save space and don't care about JSON validity errors - only GeoJSON errors - you can require('geojsonhint/lib/object') to get a version of this library that bypasses jsonlint-lines and provides only the object interface.

use it

npm (node.js, browserify, webpack, etc)

npm install --save @mapbox/geojsonhint

CDN / script tag

Hit this URL to resolve to the latest pinned version.

https://unpkg.com/@mapbox/geojsonhint@latest/geojsonhint.js

As a command-line utility

Install:

npm install -g @mapbox/geojsonhint
➟ geojsonhint
Usage: geojsonhint FILE.geojson

Options:
  --json  output json-formatted data for hints
➟ geojsonhint test.geojson
line 9, each element in a position must be a number

Development

  • Tests: npm test
  • Building the browser version: npm run build

See Also

geojsonhint's People

Contributors

a-s8h avatar badiuoanaalexandra avatar bhousel avatar chriswhong avatar derhuerst avatar flippmoke avatar geobrando avatar ingalls avatar jidanni avatar mapsam avatar mcwhittemore avatar moham-p avatar npmcdn-to-unpkg-bot avatar ozqu avatar perrygeo avatar rurban avatar rzoller avatar sckott avatar stutrek avatar tmcw avatar tyrasd avatar watson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

geojsonhint's Issues

Right hand rule for polygons + outdated NPM

The current version is not handling RHR correctly, but seems like @rurban made a fix (see #81)

According to RFC 7946, exterior rings are counter-clockwise, and opposite for interiors.

Would be nice to have this merged to master, and publish a new NPM (the latest version there is 2.0.0)

Here is a sample MultiPolygon that should be correct, but fails validation:

{
  "type":"MultiPolygon",
  "coordinates":[
    [
      [
        [
          -149.92383493947585,
          -107.20901451037372
        ],
        [
          -259.59381502763006,
          -109.20301414834012
        ],
        [
          -258.2644819356524,
          -134.460342895915
        ],
        [
          -203.09715861858095,
          -141.77167490179193
        ],
        [
          -140.61850329563254,
          -125.81967779806041
        ],
        [
          -149.92383493947585,
          -107.20901451037372
        ]
      ],
      [
        [
          -254.4534848633285,
          -128.68537469897
        ],
        [
          -252.63985750747375,
          -113.16878509887954
        ],
        [
          -241.1746460656409,
          -113.77221728002854
        ],
        [
          -239.54032744438703,
          -128.88966452662675
        ],
        [
          -254.4534848633285,
          -128.68537469897
        ]
      ],
      [
        [
          -211.55262105541485,
          -114.18079693534207
        ],
        [
          -198.47807208538396,
          -125.41673745646227
        ],
        [
          -222.17569209356486,
          -126.02960693943254
        ],
        [
          -211.55262105541485,
          -114.18079693534207
        ]
      ]
    ],
    [
      [
        [
          -217.05515608434595,
          -92.58635049861982
        ],
        [
          -241.64781828593203,
          -65.33502211307837
        ],
        [
          -263.58181430356285,
          -92.58635049861982
        ],
        [
          -217.05515608434595,
          -92.58635049861982
        ]
      ]
    ],
    [
      [
        [
          -154.57650076139757,
          -62.01168938313447
        ],
        [
          -190.46849424479345,
          -62.67635592912325
        ],
        [
          -190.46849424479345,
          -92.58635049861982
        ],
        [
          -150.58850148546466,
          -95.24501668257506
        ],
        [
          -154.57650076139757,
          -62.01168938313447
        ]
      ],
      [
        [
          -183.15633501112902,
          -68.82845519554763
        ],
        [
          -161.2973234518588,
          -68.82845519554763
        ],
        [
          -160.48016414123182,
          -87.2145396846534
        ],
        [
          -183.36062483878575,
          -87.2145396846534
        ],
        [
          -183.15633501112902,
          -68.82845519554763
        ]
      ]
    ]
  ]
}

Validator says id must be string; draft spec says number is OK

This code currently requires "id" to be a string, but I think a number is also valid. The latest GeoJSON draft spec I can find says "value of this member is either a JSON string or number". As a practical matter, QGIS emits GeoJSON with integer IDs and so right now you have to hand-edit its output to put it into geojson.io.

Issue #20 also covers this question and was closed saying the string-only behavior is correct, but I think the decision is based on a misunderstanding of what finally got committed to the spec. See here:
geojson/draft-geojson@ceb8d6a#diff-1261ada59649c3fc43efdedc43f6173b

My apologies if opening a new issue is bad etiquette, and thanks for these great tools! –Nelson

@mapbox/geojsonhint on npm has a syntax error in it

In package/geojsonhint.js line 952 + context

errors.push({
                :qa

                    message: 'The geometries array in a GeometryCollection must contain only geometry objects',
                    line: geometryCollection.__line__
                });

The error is the ':qa' that appears in the middle of the line. Is this from the build process or some other error? The version of the package called just 'geojsonhint' doesn't have this problem.

"Maximum call stack size exceeded" working with large MultiPolygon's

/Users/contra/Projects/staeco/node_modules/geojsonhint/object.js:151
                coords.forEach(function(c) {
                       ^

RangeError: Maximum call stack size exceeded
    at Array.forEach (native)
    at positionArray (/Users/contra/Projects/staeco/node_modules/geojsonhint/object.js:151:24)
    at /Users/contra/Projects/staeco/node_modules/geojsonhint/object.js:152:21
    at Array.forEach (native)
    at positionArray (/Users/contra/Projects/staeco/node_modules/geojsonhint/object.js:151:24)
    at Object.MultiPolygon (/Users/contra/Projects/staeco/node_modules/geojsonhint/object.js:224:13)
    at root (/Users/contra/Projects/staeco/node_modules/geojsonhint/object.js:35:26)
    at Object.hint (/Users/contra/Projects/staeco/node_modules/geojsonhint/object.js:319:5)
    at Object.hint (/Users/contra/Projects/staeco/node_modules/geojsonhint/index.js:38:46)
    at Object.normalizeGeoJsonGeometry (/Users/contra/Projects/staeco/node_modules/knex-postgis/lib/utils.js:8:28)
    at Formatter.wrapGeoJSON (/Users/contra/Projects/staeco/node_modules/knex-postgis/lib/index.js:58:18)
    at Object.postgis.geomFromGeoJSON (/Users/contra/Projects/staeco/node_modules/knex-postgis/lib/functions.js:93:59)
    at onBoundary (seed.js:50:32)
    at /Users/contra/Projects/staeco/node_modules/async/dist/async.js:4637:20
    at replenish (/Users/contra/Projects/staeco/node_modules/async/dist/async.js:871:21)
    at /Users/contra/Projects/staeco/node_modules/async/dist/async.js:877:29
    at /Users/contra/Projects/staeco/node_modules/async/dist/async.js:840:20
    at onBoundary (seed.js:53:7)
    at /Users/contra/Projects/staeco/node_modules/async/dist/async.js:4637:20
    at replenish (/Users/contra/Projects/staeco/node_modules/async/dist/async.js:871:21)
    at /Users/contra/Projects/staeco/node_modules/async/dist/async.js:877:29
    at /Users/contra/Projects/staeco/node_modules/async/dist/async.js:840:20

Working with city boundaries.

filtering hints by type

thanks for this tool! i'm trying to use this to validate GeoJSON coming from a web service, so i'm interested only in the fact that the response is valid GeoJSON.

reading the GeoJSON spec, it sounds a lot like the "old-style crs member is not recommended" warning should be labeled as a warning:

OGC CRS URNs such as urn:ogc:def:crs:OGC:1.3:CRS84 shall be preferred over legacy identifiers such as EPSG:4326.

I'd like to propose to add a level field to all hints returned by hint(data). others could continue using this lib just like before, but it would be possible to tell if data is outright invalid or just doesn't comply with recommendations.

Big file support for /geojsonhint

geojsonhint is fast enough to process big files but the DOM/CodeMirror is bringing me down. I should look into what it'd mean to have just errors / success shown and small chunks of context instead of the full file.

Consider returning more uniform error objects

Currently it's quite difficult to check for valid geojson, instead of just linting.

Different errors return completely different messages, for example:

Spelling error:

var errors = geojsonhint.hint("{
  "type": "FeatureCollection",
  "features": [
    {
      "typde": "Feature", // <- spelling 
    (...)
}");

console.log(errors) ->
[{
    line : 1,
    message : ""type" member required"
}]

Empty string:

var errors = geojsonhint.hint("");

console.log(errors) ->
[{
    error : {...},
    line : 0, 
    message : "Parse error..."
}]

Valid, but not perfect, GeoJSON:

var errors = geojsonhint.hint("{some valid geojson}");

console.log(errors) ->
[{
    level : "message",
    message : "Polygons and MultiPolygons should follow the right-hand rule"
},
{
    level : "message",
    message : "Polygons and MultiPolygons should follow the right-hand rule"
}]

Three different cases yield three completely different error objects, making it impossible to simply check for valid GeoJSON.

Would be great to get a more uniform error object, eg.:

[{
    level : "error",
    message : "Parse error",
    error : {...},
    line : NaN,
}, 
{
    level : "message",
    message : "Polygons and MultiPolygons should follow the right-hand rule",
    error : null, 
    line : 0
}]

link to spec to further explain errors and warnings

Internally, use the url property to point to the relevant section in the ietf spec

{
  message: "This is an error",
  url: "https://...",
  ...
}

On the command line with default format, perhaps something like

4:  Polygons and MultiPolygons should follow the right-hand rule [a]

0 errors
1 warning

References:
[a] https://...

async usage?

for web applications where users can send up geojson, it would be great if this gave the event loop some time to breathe especially on large multipolygons. the recursive tight loops will choke it up for up to a second sometimes, which is really bad.

possible solutions:

  • run it in a worker
  • use setImmediate between loop iterations so it doesn't choke the process for a second straight

if interested i can send a PR, otherwise will fork as geojsonhint-async

Geometry null

Hi,

"geometry: null" should be listed as an error. Turf ( or Mapbox gl) are throwing an error with this.

Thanks !

Maybe something like this :

        if (geom === null) {
            errors.push({
                message: 'geometry could not be null',
                line: geom.__line__
            });
        }

This will fail:

{
  "type": "FeatureCollection",
  "crs": {
    "type": "name",
    "properties": {
      "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
    }
  },
  "features": [
    {
      "type": "Feature",
      "properties": {
        "Label": "Tertiary"
      },
      "geometry": null
    },
    {
      "type": "Feature",
      "properties": {
        "Label": "Secondary"
      },
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [
            66.599966,
            36.997548
          ],
          [
            66.603196,
            36.99737
          ],
          [
            66.607052,
            36.997655
          ]
        ]
      }
    }
  ]
}

Mark geojsonhint as deprecated

Using npm deprecate. 3.0.1 will almost certainly be the last release. Please make plans to check GeoJSON using some other package in the future.

inner rings are actually inside

this one might be tricky to test but the subsequent rings in an polygon should all be located inside the first one. Tricky because they could be concave, off the top of my head unless you can think of a better one we'd need to make sure that at least one point from the inner ring is inside the outer polygon and that they don't intersect.

Treatment of NaN as a valid number

Currently NaN in coordinate arrays is treated as valid, what do you think about changing that behavior to treat NaN as invalid? PR with the minimal changeset: #72

If this seems reasonable I can add and edit test cases as necessary to reflect the behavior.

Turn off precision warning by default

I don't think that this warning makes sense for geojsonhint by default. Even if it's a warning, there are way too many cases where it's irrelevant: when GeoJSON objects are in memory, or have been processed by some algorithm, there's no point to reducing decimal accuracy since the coordinates will be stored as floating point values regardless of used precision. In the Studio case, this was surprising and we had to turn it off, and given the scarcity of tools that do truncate precision, I just don't think it's typically useful or accurate.

Inverted RightHandRule logic?

As far as I can tell, the logic introduced in 957389f (for #48 and rfc7946) is just the opposite of what it should be‽

I've created some test data, where only the counterclockwise winding gets a warning by geojsonhint: https://gist.github.com/tyrasd/2fcc5aefd988bf6b02a29b8c6e63ef9b (you can also test that by posting the data into http://geojsonlint.com/, which has recently updated its copy of geojsonhint).

$ geojsonhint counterclockwise.geojson 
    6:1  warning  Polygons and MultiPolygons should follow the right-hand rule
  
  ⚠ 1 warning
$ geojsonhint clockwise.geojson 
$

Here's what the specs say about ring winding:

A linear ring MUST follow the right-hand rule with respect to the area it bounds, i.e., exterior rings are counterclockwise, and holes are clockwise.

Define behavior for SHOULD / SHOULD NOT rules

RFC7946 says:

Implementations SHOULD NOT extend positions beyond three elements because the semantics of extra elements are unspecified and ambiguous.

And RFC2119 says:

  1. SHOULD NOT This phrase, or the phrase "NOT RECOMMENDED" mean that there may exist valid reasons in particular circumstances when the particular behavior is acceptable or even useful, but the full implications should be understood and the case carefully weighed before implementing any behavior described with this label.

So I would assume that having positions with more than three elements would be acceptable "in particular circumstances", but geojsonhint refuses them with an error.

I think this should either be a warning, or it should be made clear that geojsonhint interprets violations SHOULD / SHOULD NOT rules of the spec as errors.

simply object-based sub-file

This should reorganize the source so you can do

// default auto-detection logic
var hint = require('geojsonhint');
// don't include jsonlint-lines at all
var hint = require('geojsonhint/object');

polygon with crossing edges

Would it be possible to add a "polygon with crossing edges" warning in geojsonhint ?
mongodb 2dsphere index doesn't support such polygons and I would like detec it in advance

image

Planning for IETF draft spec

Based on Appendix B of the draft IETF GeoJSON spec here are some additional tests we may want to add to bring geojsonhint in line with the upcoming spec

  • positions can have 2 or 3 elements (lon, lat) or (lon, lat, elev)
  • objects may have extensions
  • position cannot have < 2 elements
  • position should not have > 3 elements
  • bbox for a feature collection which crosses the antimeridian should use WSEN (not minx, miny, maxx, maxy)
  • geometries crossing the antimeridian are cut (recommendation)
  • extensions must not change semantics
  • Should not have single-geometry geometry collections
  • Should not have empty geometry collections
  • Should not have nested geometry collections
  • Right-Hand Rule for polygon rings (Recommendation)
  • Warn if > X decimal places precision?
  • Non-default CRS is not recommended. It's hinted that specifying any crs object is not recommended?
  • GeoJSON types should be case-sensitive
  • bbox should be an array of 4 or 6 numeric elements

This is just a preliminary list; might have missed some and
some of these may be covered by existing tests that I didn't see on the first pass.
Can we get more 👀 on this list and help me refine it?

What shoud we do about versions? Should we allow for validation against the GJ2008 spec vs IETF spec?

cc @sgillies

Non-number members in coordinates ignored

The spec says that all members of a position array must be numbers, but this code doesn't check that. It also doesn't check that there are at least two members.

{
  "type": "Point",
  "coordinates": [ 1, 2, "f" ]
}

Any way to specify expected geojson object type?

E.g.,

geojsonhint.hint(<object>, expected = "point")

Would be nice to be able to not only know if the geojson passes the linter, but if the object passed in is actually a Point if you expect it to be - Perhaps this is out of scope.

Problem with unused library functions

My name is Hernan; with a group of colleagues we are conducting a research about unused code present in dependencies of JavaScript projects. We call this functions, UFF (Unused foreign functions). We found that in most projects there exist a great amount of UFF that are being included in the final bundle.

In the case of geojsonhint (2.0.0) our tools detected approximately 14 unused function in the dependencies. Removing those functions, the size of geojasonhint bundled could be reduced at least 7% (All tests passed). I’m attaching the reduced version of your project.
geojsonhint(optimized).txt

I’ll be very grateful if you can answer me the following questions:
-Did you were aware of the existence of these unused functions in your projects?
-Do you think that this is a problem?
-Do you think that can be useful a tool for deal with this kind of problem?

Thanks in advance.

Cheers,

MultiPolygon type for a Point feature breaks geojsonhint

An error is thrown when MultiPolygon type is provided to a Point feature.

Uncaught TypeError: coords.forEach is not a function

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          -0.087890625,
          51.56341232867588
        ]
      }
    }
  ]
}

validate polygon geometry

It would be very useful to have a mode, perhaps not the default, that validates polygon geometry.

  • Winding order
  • No self-intersection
  • No holes intersecting/outside the outer ring

The validation should be at least strong enough to guarantee that any passing polygon is suitable for processing by geojson-vt. Then we could check incoming bug reports like mapbox/mapbox-gl-js#3074, mapbox/mapbox-gl-js#3032, and mapbox/mapbox-gl-js#3080 against it, point the submitters to geojsonhint when their data turns out to be invalid, and perhaps even embed it in mapbox-gl-js as a GeoJSON source preflight mechanism.

cc @tmcw @mourner @lucaswoj @springmeyer @mapsam

Invalid GeoJSON when using NULL on feature member ID

This is not according to specification. The only thing that is stated in the spec. about the identifier is the following:

If a feature has a commonly used identifier, that identifier should be included as a member of the feature object with the name "id".

http://geojson.org/geojson-spec.html#feature-objects

Since nothing else is mentioned about the type of ID, it should adhere to the JSON spec where the property of an object can be any of the following: String, Number, null, true, false, Array or Object

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.