diff options
| author | Even Rouault <even.rouault@spatialys.com> | 2019-07-06 17:06:23 +0200 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2019-07-08 00:05:00 +0200 |
| commit | ece151aed1b4bf2634de5759f37fd7bc005e8313 (patch) | |
| tree | 8e2e38daaffc878cc3ba673857e66274555e3dcc /src/iso19111 | |
| parent | 17f0b0b3bc65ffba39bf6f22a12b2cc7fcb9bafd (diff) | |
| download | PROJ-ece151aed1b4bf2634de5759f37fd7bc005e8313.tar.gz PROJ-ece151aed1b4bf2634de5759f37fd7bc005e8313.zip | |
CRS JSON: export GeographicCRS and Projected CRS
Diffstat (limited to 'src/iso19111')
| -rw-r--r-- | src/iso19111/common.cpp | 84 | ||||
| -rw-r--r-- | src/iso19111/coordinateoperation.cpp | 85 | ||||
| -rw-r--r-- | src/iso19111/coordinatesystem.cpp | 59 | ||||
| -rw-r--r-- | src/iso19111/crs.cpp | 160 | ||||
| -rw-r--r-- | src/iso19111/datum.cpp | 106 | ||||
| -rw-r--r-- | src/iso19111/io.cpp | 61 | ||||
| -rw-r--r-- | src/iso19111/metadata.cpp | 2 |
7 files changed, 541 insertions, 16 deletions
diff --git a/src/iso19111/common.cpp b/src/iso19111/common.cpp index f2a51032..fb7a63c0 100644 --- a/src/iso19111/common.cpp +++ b/src/iso19111/common.cpp @@ -243,7 +243,9 @@ void UnitOfMeasure::_exportToJSON( JSONFormatter *formatter) const // throw(FormattingException) { auto &writer = formatter->writer(); - PROJ::CPLJSonStreamingWriter::ObjectContext objContext(writer); + const auto &l_codeSpace = codeSpace(); + auto objContext( + formatter->MakeObjectContext(nullptr, !l_codeSpace.empty())); writer.AddObjKey("type"); const auto l_type = type(); if (l_type == Type::LINEAR) { @@ -268,10 +270,9 @@ void UnitOfMeasure::_exportToJSON( writer.AddObjKey("conversion_factor"); writer.Add(factor, 15); - const auto &l_codeSpace = codeSpace(); if (!l_codeSpace.empty() && formatter->outputId()) { writer.AddObjKey("id"); - PROJ::CPLJSonStreamingWriter::ObjectContext idContext(writer); + auto idContext(formatter->MakeObjectContext(nullptr, false)); writer.AddObjKey("authority"); writer.Add(l_codeSpace); writer.AddObjKey("code"); @@ -871,7 +872,7 @@ void IdentifiedObject::formatID(JSONFormatter *formatter) const { ids.front()->_exportToJSON(formatter); } else if (!ids.empty()) { writer.AddObjKey("ids"); - PROJ::CPLJSonStreamingWriter::ArrayContext arrayContext(writer); + auto arrayContext(writer.MakeArrayContext()); for (const auto &id : ids) { id->_exportToJSON(formatter); } @@ -880,6 +881,16 @@ void IdentifiedObject::formatID(JSONFormatter *formatter) const { // --------------------------------------------------------------------------- +void IdentifiedObject::formatRemarks(JSONFormatter *formatter) const { + if (!remarks().empty()) { + auto &writer = formatter->writer(); + writer.AddObjKey("remarks"); + writer.Add(remarks()); + } +} + +// --------------------------------------------------------------------------- + bool IdentifiedObject::_isEquivalentTo( const util::IComparable *other, util::IComparable::Criterion criterion) const { @@ -1031,6 +1042,46 @@ void ObjectDomain::_exportToWKT(WKTFormatter *formatter) const { // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress +void ObjectDomain::_exportToJSON(JSONFormatter *formatter) const { + auto &writer = formatter->writer(); + if (d->scope_.has_value()) { + writer.AddObjKey("scope"); + writer.Add(*(d->scope_)); + } + if (d->domainOfValidity_) { + if (d->domainOfValidity_->description().has_value()) { + writer.AddObjKey("area"); + writer.Add(*(d->domainOfValidity_->description())); + } + if (d->domainOfValidity_->geographicElements().size() == 1) { + const auto bbox = dynamic_cast<const GeographicBoundingBox *>( + d->domainOfValidity_->geographicElements()[0].get()); + if (bbox) { + writer.AddObjKey("bbox"); + auto bboxContext(writer.MakeObjectContext()); + writer.AddObjKey("south_latitude"); + writer.Add(bbox->southBoundLatitude(), 15); + writer.AddObjKey("west_longitude"); + writer.Add(bbox->westBoundLongitude(), 15); + writer.AddObjKey("north_latitude"); + writer.Add(bbox->northBoundLatitude(), 15); + writer.AddObjKey("east_longitude"); + writer.Add(bbox->eastBoundLongitude(), 15); + } + } + if (d->domainOfValidity_->verticalElements().size() == 1) { + // TODO + } + if (d->domainOfValidity_->temporalElements().size() == 1) { + // TODO + } + } +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress bool ObjectDomain::_isEquivalentTo( const util::IComparable *other, util::IComparable::Criterion criterion) const { @@ -1162,6 +1213,31 @@ void ObjectUsage::baseExportToWKT(WKTFormatter *formatter) const { // --------------------------------------------------------------------------- +void ObjectUsage::baseExportToJSON(JSONFormatter *formatter) const { + + auto &writer = formatter->writer(); + if (formatter->outputUsage()) { + const auto &l_domains = domains(); + if (l_domains.size() == 1) { + l_domains[0]->_exportToJSON(formatter); + } else if (!l_domains.empty()) { + writer.AddObjKey("usages"); + auto arrayContext(writer.MakeArrayContext(false)); + for (const auto &domain : l_domains) { + auto objContext(writer.MakeObjectContext()); + domain->_exportToJSON(formatter); + } + } + } + + if (formatter->outputId()) { + formatID(formatter); + } + formatRemarks(formatter); +} + +// --------------------------------------------------------------------------- + //! @cond Doxygen_Suppress bool ObjectUsage::_isEquivalentTo( const util::IComparable *other, diff --git a/src/iso19111/coordinateoperation.cpp b/src/iso19111/coordinateoperation.cpp index 7f3a2137..a2a31edd 100644 --- a/src/iso19111/coordinateoperation.cpp +++ b/src/iso19111/coordinateoperation.cpp @@ -991,6 +991,24 @@ void OperationMethod::_exportToWKT(io::WKTFormatter *formatter) const { // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress +void OperationMethod::_exportToJSON( + io::JSONFormatter *formatter) const // throw(FormattingException) +{ + auto &writer = formatter->writer(); + auto objectContext(formatter->MakeObjectContext("OperationMethod", + !identifiers().empty())); + + writer.AddObjKey("name"); + writer.Add(nameStr()); + + if (formatter->outputId()) { + formatID(formatter); + } +} + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress bool OperationMethod::_isEquivalentTo( const util::IComparable *other, util::IComparable::Criterion criterion) const { @@ -1168,6 +1186,35 @@ void OperationParameterValue::_exportToWKT(io::WKTFormatter *formatter, // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress +void OperationParameterValue::_exportToJSON( + io::JSONFormatter *formatter) const { + auto &writer = formatter->writer(); + auto objectContext(formatter->MakeObjectContext( + "ParameterValue", !parameter()->identifiers().empty())); + + writer.AddObjKey("name"); + writer.Add(parameter()->nameStr()); + + const auto &l_value(parameterValue()); + if (l_value->type() == ParameterValue::Type::MEASURE) { + writer.AddObjKey("value"); + writer.Add(l_value->value().value(), 15); + writer.AddObjKey("unit"); + l_value->value().unit()._exportToJSON(formatter); + } else if (l_value->type() == ParameterValue::Type::FILENAME) { + writer.AddObjKey("value"); + writer.Add(l_value->valueFile()); + } + + if (formatter->outputId()) { + parameter()->formatID(formatter); + } +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress /** Utility method used on WKT2 import to convert from abridged transformation * to "normal" transformation parameters. @@ -5410,6 +5457,44 @@ void Conversion::_exportToWKT(io::WKTFormatter *formatter) const { // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress +void Conversion::_exportToJSON( + io::JSONFormatter *formatter) const // throw(FormattingException) +{ + auto &writer = formatter->writer(); + auto objectContext( + formatter->MakeObjectContext("Conversion", !identifiers().empty())); + + writer.AddObjKey("name"); + auto l_name = nameStr(); + if (l_name.empty()) { + writer.Add("unnamed"); + } else { + writer.Add(l_name); + } + + writer.AddObjKey("method"); + formatter->setAllowIDInImmediateChild(); + method()->_exportToJSON(formatter); + + writer.AddObjKey("parameters"); + { + auto parametersContext(writer.MakeArrayContext(false)); + for (const auto &genOpParamvalue : parameterValues()) { + formatter->setAllowIDInImmediateChild(); + genOpParamvalue->_exportToJSON(formatter); + } + } + + if (formatter->outputId()) { + formatID(formatter); + } +} + +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress static bool createPROJ4WebMercator(const Conversion *conv, io::PROJStringFormatter *formatter) { const double centralMeridian = conv->parameterValueNumeric( diff --git a/src/iso19111/coordinatesystem.cpp b/src/iso19111/coordinatesystem.cpp index ef9cac93..f96a962f 100644 --- a/src/iso19111/coordinatesystem.cpp +++ b/src/iso19111/coordinatesystem.cpp @@ -311,8 +311,8 @@ void CoordinateSystemAxis::_exportToWKT(io::WKTFormatter *formatter, int order, bool disableAbbrev) const { const bool isWKT2 = formatter->version() == io::WKTFormatter::Version::WKT2; formatter->startNode(io::WKTConstants::AXIS, !identifiers().empty()); - std::string axisName = *(name()->description()); - std::string abbrev = abbreviation(); + const std::string &axisName = nameStr(); + const std::string &abbrev = abbreviation(); std::string parenthesizedAbbrev = "(" + abbrev + ")"; std::string dir = direction().toString(); std::string axisDesignation; @@ -393,6 +393,34 @@ void CoordinateSystemAxis::_exportToWKT(io::WKTFormatter *formatter, int order, // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress +void CoordinateSystemAxis::_exportToJSON( + io::JSONFormatter *formatter) const // throw(FormattingException) +{ + auto &writer = formatter->writer(); + auto objectContext( + formatter->MakeObjectContext("Axis", !identifiers().empty())); + + writer.AddObjKey("name"); + writer.Add(nameStr()); + + writer.AddObjKey("abbreviation"); + writer.Add(abbreviation()); + + writer.AddObjKey("direction"); + writer.Add(direction().toString()); + + writer.AddObjKey("unit"); + unit()._exportToJSON(formatter); + + if (formatter->outputId()) { + formatID(formatter); + } +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress bool CoordinateSystemAxis::_isEquivalentTo( const util::IComparable *other, util::IComparable::Criterion criterion) const { @@ -535,6 +563,33 @@ void CoordinateSystem::_exportToWKT( // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress +void CoordinateSystem::_exportToJSON( + io::JSONFormatter *formatter) const // throw(FormattingException) +{ + auto &writer = formatter->writer(); + auto objectContext(formatter->MakeObjectContext("CoordinateSystem", + !identifiers().empty())); + + writer.AddObjKey("subtype"); + writer.Add(getWKT2Type(true)); + + writer.AddObjKey("axis"); + auto axisContext(writer.MakeArrayContext(false)); + const auto &l_axisList = axisList(); + for (auto &axis : l_axisList) { + axis->_exportToJSON(formatter); + } + + if (formatter->outputId()) { + formatID(formatter); + } +} + +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress bool CoordinateSystem::_isEquivalentTo( const util::IComparable *other, util::IComparable::Criterion criterion) const { diff --git a/src/iso19111/crs.cpp b/src/iso19111/crs.cpp index 476bc72b..2ca2786d 100644 --- a/src/iso19111/crs.cpp +++ b/src/iso19111/crs.cpp @@ -1342,6 +1342,39 @@ void GeodeticCRS::addDatumInfoToPROJString( // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress +void GeodeticCRS::_exportToJSON( + io::JSONFormatter *formatter) const // throw(io::FormattingException) +{ + auto &writer = formatter->writer(); + auto objectContext( + formatter->MakeObjectContext("GeodeticCRS", !identifiers().empty())); + + writer.AddObjKey("name"); + auto l_name = nameStr(); + if (l_name.empty()) { + writer.Add("unnamed"); + } else { + writer.Add(l_name); + } + + const auto &l_datum(datum()); + if (l_datum) { + writer.AddObjKey("datum"); + l_datum->_exportToJSON(formatter); + } else { + // TODO DatumEnsemble + } + + writer.AddObjKey("coordinate_system"); + coordinateSystem()->_exportToJSON(formatter); + + ObjectUsage::baseExportToJSON(formatter); +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress static util::IComparable::Criterion getStandardCriterion(util::IComparable::Criterion criterion) { return criterion == util::IComparable::Criterion:: @@ -2059,6 +2092,39 @@ void GeographicCRS::_exportToPROJString( // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress +void GeographicCRS::_exportToJSON( + io::JSONFormatter *formatter) const // throw(io::FormattingException) +{ + auto &writer = formatter->writer(); + auto objectContext( + formatter->MakeObjectContext("GeographicCRS", !identifiers().empty())); + + writer.AddObjKey("name"); + auto l_name = nameStr(); + if (l_name.empty()) { + writer.Add("unnamed"); + } else { + writer.Add(l_name); + } + + const auto &l_datum(datum()); + if (l_datum) { + writer.AddObjKey("datum"); + l_datum->_exportToJSON(formatter); + } else { + // TODO DatumEnsemble + } + + writer.AddObjKey("coordinate_system"); + coordinateSystem()->_exportToJSON(formatter); + + ObjectUsage::baseExportToJSON(formatter); +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress struct VerticalCRS::Private { std::vector<operation::TransformationNNPtr> geoidModel{}; std::vector<operation::PointMotionOperationNNPtr> velocityModel{}; @@ -2856,6 +2922,38 @@ void ProjectedCRS::_exportToWKT(io::WKTFormatter *formatter) const { // --------------------------------------------------------------------------- +//! @cond Doxygen_Suppress +void ProjectedCRS::_exportToJSON( + io::JSONFormatter *formatter) const // throw(io::FormattingException) +{ + auto &writer = formatter->writer(); + auto objectContext( + formatter->MakeObjectContext("ProjectedCRS", !identifiers().empty())); + + writer.AddObjKey("name"); + auto l_name = nameStr(); + if (l_name.empty()) { + writer.Add("unnamed"); + } else { + writer.Add(l_name); + } + + writer.AddObjKey("base_crs"); + formatter->setAllowIDInImmediateChild(); + baseCRS()->_exportToJSON(formatter); + + writer.AddObjKey("conversion"); + derivingConversionRef()->_exportToJSON(formatter); + + writer.AddObjKey("coordinate_system"); + coordinateSystem()->_exportToJSON(formatter); + + ObjectUsage::baseExportToJSON(formatter); +} +//! @endcond + +// --------------------------------------------------------------------------- + void ProjectedCRS::_exportToPROJString( io::PROJStringFormatter *formatter) const // throw(io::FormattingException) { @@ -4195,6 +4293,37 @@ void DerivedGeodeticCRS::_exportToWKT(io::WKTFormatter *formatter) const { // --------------------------------------------------------------------------- +//! @cond Doxygen_Suppress +void DerivedGeodeticCRS::_exportToJSON( + io::JSONFormatter *formatter) const // throw(io::FormattingException) +{ + auto &writer = formatter->writer(); + auto objectContext(formatter->MakeObjectContext("DerivedGeodeticCRS", + !identifiers().empty())); + + writer.AddObjKey("name"); + auto l_name = nameStr(); + if (l_name.empty()) { + writer.Add("unnamed"); + } else { + writer.Add(l_name); + } + + writer.AddObjKey("base_crs"); + baseCRS()->_exportToJSON(formatter); + + writer.AddObjKey("conversion"); + derivingConversionRef()->_exportToJSON(formatter); + + writer.AddObjKey("coordinate_system"); + coordinateSystem()->_exportToJSON(formatter); + + ObjectUsage::baseExportToJSON(formatter); +} +//! @endcond + +// --------------------------------------------------------------------------- + void DerivedGeodeticCRS::_exportToPROJString( io::PROJStringFormatter *) const // throw(io::FormattingException) { @@ -4333,6 +4462,37 @@ void DerivedGeographicCRS::_exportToWKT(io::WKTFormatter *formatter) const { // --------------------------------------------------------------------------- +//! @cond Doxygen_Suppress +void DerivedGeographicCRS::_exportToJSON( + io::JSONFormatter *formatter) const // throw(io::FormattingException) +{ + auto &writer = formatter->writer(); + auto objectContext(formatter->MakeObjectContext("DerivedGeographicCRS", + !identifiers().empty())); + + writer.AddObjKey("name"); + auto l_name = nameStr(); + if (l_name.empty()) { + writer.Add("unnamed"); + } else { + writer.Add(l_name); + } + + writer.AddObjKey("base_crs"); + baseCRS()->_exportToJSON(formatter); + + writer.AddObjKey("conversion"); + derivingConversionRef()->_exportToJSON(formatter); + + writer.AddObjKey("coordinate_system"); + coordinateSystem()->_exportToJSON(formatter); + + ObjectUsage::baseExportToJSON(formatter); +} +//! @endcond + +// --------------------------------------------------------------------------- + void DerivedGeographicCRS::_exportToPROJString( io::PROJStringFormatter *) const // throw(io::FormattingException) { diff --git a/src/iso19111/datum.cpp b/src/iso19111/datum.cpp index 6ba219d4..89ecc755 100644 --- a/src/iso19111/datum.cpp +++ b/src/iso19111/datum.cpp @@ -93,6 +93,9 @@ struct Datum::Private { // cppcheck-suppress functionStatic void exportAnchorDefinition(io::WKTFormatter *formatter) const; + + // cppcheck-suppress functionStatic + void exportAnchorDefinition(io::JSONFormatter *formatter) const; }; // --------------------------------------------------------------------------- @@ -105,6 +108,17 @@ void Datum::Private::exportAnchorDefinition(io::WKTFormatter *formatter) const { } } +// --------------------------------------------------------------------------- + +void Datum::Private::exportAnchorDefinition( + io::JSONFormatter *formatter) const { + if (anchorDefinition) { + auto &writer = formatter->writer(); + writer.AddObjKey("anchor"); + writer.Add(*anchorDefinition); + } +} + //! @endcond // --------------------------------------------------------------------------- @@ -352,10 +366,8 @@ void PrimeMeridian::_exportToJSON( io::JSONFormatter *formatter) const // throw(FormattingException) { auto &writer = formatter->writer(); - PROJ::CPLJSonStreamingWriter::ObjectContext objectContext(writer); - - writer.AddObjKey("type"); - writer.Add("PrimeMeridian"); + auto objectContext( + formatter->MakeObjectContext("PrimeMeridian", !identifiers().empty())); writer.AddObjKey("name"); std::string l_name = @@ -365,7 +377,7 @@ void PrimeMeridian::_exportToJSON( const auto &l_long = longitude(); writer.AddObjKey("longitude"); { - PROJ::CPLJSonStreamingWriter::ObjectContext longitudeContext(writer); + auto longitudeContext(formatter->MakeObjectContext(nullptr, false)); writer.AddObjKey("value"); writer.Add(l_long.value(), 15); @@ -803,6 +815,60 @@ void Ellipsoid::_exportToWKT( // --------------------------------------------------------------------------- +//! @cond Doxygen_Suppress +void Ellipsoid::_exportToJSON( + io::JSONFormatter *formatter) const // throw(FormattingException) +{ + auto &writer = formatter->writer(); + auto objectContext( + formatter->MakeObjectContext("Ellipsoid", !identifiers().empty())); + + writer.AddObjKey("name"); + auto l_name = nameStr(); + if (l_name.empty()) { + writer.Add("unnamed"); + } else { + writer.Add(l_name); + } + + const auto &semiMajor = semiMajorAxis(); + const auto &semiMajorUnit = semiMajor.unit(); + writer.AddObjKey(isSphere() ? "radius" : "semi_major_axis"); + { + auto objContext(formatter->MakeObjectContext(nullptr, false)); + writer.AddObjKey("value"); + writer.Add(semiMajor.value(), 15); + + writer.AddObjKey("unit"); + semiMajorUnit._exportToJSON(formatter); + } + + if (!isSphere()) { + const auto &l_inverseFlattening = inverseFlattening(); + if (l_inverseFlattening.has_value()) { + writer.AddObjKey("inverse_flattening"); + writer.Add(l_inverseFlattening->getSIValue(), 15); + } else { + writer.AddObjKey("semi_minor_axis"); + { + auto objContext(formatter->MakeObjectContext(nullptr, false)); + writer.AddObjKey("value"); + writer.Add(semiMinorAxis()->value(), 15); + + writer.AddObjKey("unit"); + semiMinorAxis()->unit()._exportToJSON(formatter); + } + } + } + + if (formatter->outputId()) { + formatID(formatter); + } +} +//! @endcond + +// --------------------------------------------------------------------------- + bool Ellipsoid::lookForProjWellKnownEllps(std::string &projEllpsName, std::string &ellpsName) const { const double a = semiMajorAxis().getSIValue(); @@ -1188,6 +1254,36 @@ void GeodeticReferenceFrame::_exportToWKT( // --------------------------------------------------------------------------- //! @cond Doxygen_Suppress +void GeodeticReferenceFrame::_exportToJSON( + io::JSONFormatter *formatter) const // throw(FormattingException) +{ + auto objectContext(formatter->MakeObjectContext("GeodeticReferenceFrame", + !identifiers().empty())); + auto &writer = formatter->writer(); + + writer.AddObjKey("name"); + auto l_name = nameStr(); + if (l_name.empty()) { + writer.Add("unnamed"); + } else { + writer.Add(l_name); + } + + Datum::getPrivate()->exportAnchorDefinition(formatter); + + writer.AddObjKey("ellipsoid"); + ellipsoid()->_exportToJSON(formatter); + + writer.AddObjKey("prime_meridian"); + primeMeridian()->_exportToJSON(formatter); + + ObjectUsage::baseExportToJSON(formatter); +} +//! @endcond + +// --------------------------------------------------------------------------- + +//! @cond Doxygen_Suppress bool GeodeticReferenceFrame::_isEquivalentTo( const util::IComparable *other, util::IComparable::Criterion criterion) const { diff --git a/src/iso19111/io.cpp b/src/iso19111/io.cpp index 0c9f8a0c..35798d9d 100644 --- a/src/iso19111/io.cpp +++ b/src/iso19111/io.cpp @@ -8021,9 +8021,20 @@ PROJStringParser::createFromPROJString(const std::string &projString) { //! @cond Doxygen_Suppress struct JSONFormatter::Private { - PROJ::CPLJSonStreamingWriter writer_{nullptr, nullptr}; + CPLJSonStreamingWriter writer_{nullptr, nullptr}; DatabaseContextPtr dbContext_{}; + + std::vector<bool> stackHasId_{false}; + std::vector<bool> outputIdStack_{true}; + bool allowIDInImmediateChild_ = false; + std::string result_{}; + + // cppcheck-suppress functionStatic + void pushOutputId(bool outputIdIn) { outputIdStack_.push_back(outputIdIn); } + + // cppcheck-suppress functionStatic + void popOutputId() { outputIdStack_.pop_back(); } }; //! @endcond @@ -8071,13 +8082,55 @@ JSONFormatter::~JSONFormatter() = default; // --------------------------------------------------------------------------- -PROJ::CPLJSonStreamingWriter &JSONFormatter::writer() const { - return d->writer_; +CPLJSonStreamingWriter &JSONFormatter::writer() const { return d->writer_; } + +// --------------------------------------------------------------------------- + +bool JSONFormatter::outputId() const { return d->outputIdStack_.back(); } + +// --------------------------------------------------------------------------- + +bool JSONFormatter::outputUsage() const { + return outputId() && d->outputIdStack_.size() == 2; } // --------------------------------------------------------------------------- -bool JSONFormatter::outputId() const { return true; } +void JSONFormatter::setAllowIDInImmediateChild() { + d->allowIDInImmediateChild_ = true; +} + +// --------------------------------------------------------------------------- + +JSONFormatter::ObjectContext::ObjectContext(JSONFormatter &formatter, + const char *objectType, bool hasId) + : m_formatter(formatter) { + m_formatter.d->writer_.StartObj(); + if (objectType) { + m_formatter.d->writer_.AddObjKey("type"); + m_formatter.d->writer_.Add(objectType); + } + // All intermediate nodes shouldn't have ID if a parent has an ID + // unless explicitly enabled. + if (m_formatter.d->allowIDInImmediateChild_) { + m_formatter.d->pushOutputId(m_formatter.d->outputIdStack_[0]); + m_formatter.d->allowIDInImmediateChild_ = false; + } else { + m_formatter.d->pushOutputId(m_formatter.d->outputIdStack_[0] && + !m_formatter.d->stackHasId_.back()); + } + + m_formatter.d->stackHasId_.push_back(hasId || + m_formatter.d->stackHasId_.back()); +} + +// --------------------------------------------------------------------------- + +JSONFormatter::ObjectContext::~ObjectContext() { + m_formatter.d->writer_.EndObj(); + m_formatter.d->stackHasId_.pop_back(); + m_formatter.d->popOutputId(); +} //! @endcond diff --git a/src/iso19111/metadata.cpp b/src/iso19111/metadata.cpp index 761b909b..41653b32 100644 --- a/src/iso19111/metadata.cpp +++ b/src/iso19111/metadata.cpp @@ -1096,7 +1096,7 @@ void Identifier::_exportToJSON(JSONFormatter *formatter) const { const std::string &l_codeSpace = *codeSpace(); if (!l_codeSpace.empty() && !l_code.empty()) { auto &writer = formatter->writer(); - PROJ::CPLJSonStreamingWriter::ObjectContext objContext(writer); + auto objContext(formatter->MakeObjectContext(nullptr, false)); writer.AddObjKey("authority"); writer.Add(l_codeSpace); writer.AddObjKey("code"); |
