# HG changeset patch # User Sebastien Jodogne # Date 1624025315 -7200 # Node ID 569d9ef165b1341b24e4c4dca45e0d33265546da # Parent dd6274412ff4aec3853bbb1f2876ced65a791f40 Added "short", "simplify" and/or "full" options to control the format of DICOM tags wherever possible diff -r dd6274412ff4 -r 569d9ef165b1 NEWS --- a/NEWS Thu Jun 17 15:47:21 2021 +0200 +++ b/NEWS Fri Jun 18 16:08:35 2021 +0200 @@ -9,6 +9,11 @@ - "ExternalDictionaries" to load external DICOM dictionaries (useful for DICONDE) - "SynchronousZipStream" to disable streaming of ZIP +Orthanc Explorer +---------------- + +* Orthanc Explorer supports the DICONDE dictionary + REST API -------- @@ -22,6 +27,19 @@ * "/jobs/..." has new field "ErrorDetails" to help identify the cause of an error * "Replace", "Keep" and "Remove" in "/modify" and "/anonymize" accept paths to subsequences using the syntax of the dcmodify command-line tool (wildcards are supported as well) +* Added "short", "simplify" and/or "full" options to control the format of DICOM tags in: + - GET /patients, GET /studies, GET /series, GET /instances (together with "&expand") + - GET /patients/{id}, GET /studies/{id}, GET /series/{id}, GET /instances/{id} + - GET /patients/{id}/studies, GET /patients/{id}/series, GET /patients/{id}/instances + - GET /studies/{id}/patient, GET /studies/{id}/series, GET /studies/{id}/instances + - GET /series/{id}/patient, GET /series/{id}/study, GET /series/{id}/instances + - GET /instances/{id}/patient, GET /instances/{id}/study, GET /instances/{id}/series + - GET /patients/{id}/instances-tags, GET /patients/{id}/shared-tags + - GET /studies/{id}/instances-tags, GET /series/{id}/shared-tags + - GET /series/{id}/instances-tags, GET /studies/{id}/shared-tags + - GET /patients/{id}/module, GET /patients/{id}/patient-module + - GET /series/{id}/module, GET /studies/{id}/module, GET /instances/{id}/module + - POST /tools/find Maintenance ----------- diff -r dd6274412ff4 -r 569d9ef165b1 OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp --- a/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp Thu Jun 17 15:47:21 2021 +0200 +++ b/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.cpp Fri Jun 18 16:08:35 2021 +0200 @@ -1329,7 +1329,7 @@ void FromDcmtkBridge::ToJson(Json::Value& result, const DicomMap& values, - bool simplify) + DicomToJsonFormat format) { if (result.type() != Json::objectValue) { @@ -1341,40 +1341,69 @@ for (DicomMap::Content::const_iterator it = values.content_.begin(); it != values.content_.end(); ++it) { - // TODO Inject PrivateCreator if some is available in the DicomMap? - const std::string tagName = GetTagName(it->first, ""); - - if (simplify) - { - if (it->second->IsNull()) - { - result[tagName] = Json::nullValue; - } - else - { - // TODO IsBinary - result[tagName] = it->second->GetContent(); - } - } - else + switch (format) { - Json::Value value = Json::objectValue; - - value["Name"] = tagName; - - if (it->second->IsNull()) + case DicomToJsonFormat_Human: { - value["Type"] = "Null"; - value["Value"] = Json::nullValue; + // TODO Inject PrivateCreator if some is available in the DicomMap? + const std::string tagName = GetTagName(it->first, ""); + + if (it->second->IsNull()) + { + result[tagName] = Json::nullValue; + } + else + { + // TODO IsBinary + result[tagName] = it->second->GetContent(); + } + break; } - else + + case DicomToJsonFormat_Full: { - // TODO IsBinary - value["Type"] = "String"; - value["Value"] = it->second->GetContent(); + // TODO Inject PrivateCreator if some is available in the DicomMap? + const std::string tagName = GetTagName(it->first, ""); + + Json::Value value = Json::objectValue; + + value["Name"] = tagName; + + if (it->second->IsNull()) + { + value["Type"] = "Null"; + value["Value"] = Json::nullValue; + } + else + { + // TODO IsBinary + value["Type"] = "String"; + value["Value"] = it->second->GetContent(); + } + + result[it->first.Format()] = value; + break; } - result[it->first.Format()] = value; + case DicomToJsonFormat_Short: + { + const std::string hex = it->first.Format(); + + if (it->second->IsNull()) + { + result[hex] = Json::nullValue; + } + else + { + // TODO IsBinary + result[hex] = it->second->GetContent(); + } + + break; + } + + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); } } } diff -r dd6274412ff4 -r 569d9ef165b1 OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h --- a/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h Thu Jun 17 15:47:21 2021 +0200 +++ b/OrthancFramework/Sources/DicomParsing/FromDcmtkBridge.h Fri Jun 18 16:08:35 2021 +0200 @@ -176,7 +176,7 @@ static void ToJson(Json::Value& result, const DicomMap& values, - bool simplify); + DicomToJsonFormat format); static std::string GenerateUniqueIdentifier(ResourceType level); diff -r dd6274412ff4 -r 569d9ef165b1 OrthancServer/OrthancExplorer/explorer.js --- a/OrthancServer/OrthancExplorer/explorer.js Thu Jun 17 15:47:21 2021 +0200 +++ b/OrthancServer/OrthancExplorer/explorer.js Fri Jun 18 16:08:35 2021 +0200 @@ -51,6 +51,30 @@ var currentPage = ''; var currentUuid = ''; +var ACQUISITION_NUMBER = '0020,0012'; +var IMAGES_IN_ACQUISITION = '0020,1002'; +var IMAGE_ORIENTATION_PATIENT = '0020,0037'; +var IMAGE_POSITION_PATIENT = '0020,0032'; +var INSTANCE_CREATION_DATE = '0008,0012'; +var INSTANCE_CREATION_TIME = '0008,0013'; +var INSTANCE_NUMBER = '0020,0013'; +var MANUFACTURER = '0008,0070'; +var OTHER_PATIENT_IDS = '0010,1000'; +var PATIENT_BIRTH_DATE = '0010,0030'; +var PATIENT_NAME = '0010,0010'; +var SERIES_DATE = '0008,0021'; +var SERIES_DESCRIPTION = '0008,103e'; +var SERIES_INSTANCE_UID = '0020,000e'; +var SERIES_TIME = '0008,0031'; +var SOP_INSTANCE_UID = '0008,0018'; +var STUDY_DATE = '0008,0020'; +var STUDY_DESCRIPTION = '0008,1030'; +var STUDY_INSTANCE_UID = '0020,000d'; +var STUDY_TIME = '0008,0030'; + +var ANONYMIZED_FROM = 'AnonymizedFrom'; +var MODIFIED_FROM = 'ModifiedFrom'; + function DeepCopy(obj) { @@ -158,12 +182,6 @@ ); -function SplitLongUid(s) -{ - return '' + s.substr(0, s.length / 2) + ' ' + s.substr(s.length / 2, s.length - s.length / 2) + ''; -} - - function ParseDicomDate(s) { y = parseInt(s.substr(0, 4), 10); @@ -259,10 +277,20 @@ } +function GetMainDicomTag(mainDicomTags, tag) +{ + if (tag in mainDicomTags) { + return mainDicomTags[tag].Value; + } else { + return ''; + } +} + + function SortOnDicomTag(arr, tag, isInteger, reverse) { return Sort(arr, function(a) { - return a.MainDicomTags[tag]; + return GetMainDicomTag(a.MainDicomTags, tag); }, isInteger, reverse); } @@ -291,7 +319,8 @@ .text(count)); } - if (link != null) + if (link != null && + link) { node = $('').attr('href', link).append(node); @@ -316,28 +345,31 @@ { if (tagsToIgnore.indexOf(i) == -1) { - v = tags[i]; + v = GetMainDicomTag(tags, i); - if (i == "PatientBirthDate" || - i == "StudyDate" || - i == "SeriesDate") + if (i == PATIENT_BIRTH_DATE || + i == STUDY_DATE || + i == SERIES_DATE || + i == INSTANCE_CREATION_DATE) { v = FormatDicomDate(v); } - else if (i == "DicomStudyInstanceUID" || - i == "DicomSeriesInstanceUID") + else if (i == STUDY_INSTANCE_UID || + i == SERIES_INSTANCE_UID || + i == SOP_INSTANCE_UID) { - v = SplitLongUid(v); + // Possibly split a long UID + // v = '' + s.substr(0, s.length / 2) + '' + s.substr(s.length / 2, s.length - s.length / 2) + ''; } - else if (i == "ImagePositionPatient" || - i == "ImageOrientationPatient") + else if (i == IMAGE_POSITION_PATIENT || + i == IMAGE_ORIENTATION_PATIENT) { v = FormatFloatSequence(v); } target.append($('

') - .text(i + ': ') - .append($('').text(v))); + .text(tags[i].Name + ': ') + .append($('').html(v))); } } } @@ -345,11 +377,11 @@ function FormatPatient(patient, link, isReverse) { - var node = $('

').append($('

').text(patient.MainDicomTags.PatientName)); + var node = $('
').append($('

').text(GetMainDicomTag(patient.MainDicomTags, PATIENT_NAME))); FormatMainDicomTags(node, patient.MainDicomTags, [ - "PatientName" - // "OtherPatientIDs" + PATIENT_NAME + //, OTHER_PATIENT_IDS ]); return CompleteFormatting(node, link, isReverse, patient.Studies.length); @@ -365,20 +397,20 @@ if (includePatient) { label = study.Label; } else { - label = study.MainDicomTags.StudyDescription; + label = GetMainDicomTag(study.MainDicomTags, STUDY_DESCRIPTION); } node = $('
').append($('

').text(label)); if (includePatient) { FormatMainDicomTags(node, study.PatientMainDicomTags, [ - 'PatientName' + PATIENT_NAME ]); } FormatMainDicomTags(node, study.MainDicomTags, [ - 'StudyDescription', - 'StudyTime' + STUDY_DESCRIPTION, + STUDY_TIME ]); return CompleteFormatting(node, link, isReverse, study.Series.length); @@ -402,18 +434,18 @@ } node = $('
') - .append($('

').text(series.MainDicomTags.SeriesDescription)) - .append($('

').append($('') - .text('Status: ') - .append($('').text(series.Status)))); - + .append($('

').text(GetMainDicomTag(series.MainDicomTags, SERIES_DESCRIPTION))) + .append($('

').append($('') + .text('Status: ') + .append($('').text(series.Status)))); + FormatMainDicomTags(node, series.MainDicomTags, [ - "SeriesDescription", - "SeriesTime", - "Manufacturer", - "ImagesInAcquisition", - "SeriesDate", - "ImageOrientationPatient" + SERIES_DESCRIPTION, + SERIES_TIME, + MANUFACTURER, + IMAGES_IN_ACQUISITION, + SERIES_DATE, + IMAGE_ORIENTATION_PATIENT ]); return CompleteFormatting(node, link, isReverse, c); @@ -425,10 +457,10 @@ var node = $('

').append($('

').text('Instance: ' + instance.IndexInSeries)); FormatMainDicomTags(node, instance.MainDicomTags, [ - "AcquisitionNumber", - "InstanceNumber", - "InstanceCreationDate", - "InstanceCreationTime" + ACQUISITION_NUMBER, + INSTANCE_NUMBER, + INSTANCE_CREATION_DATE, + INSTANCE_CREATION_TIME, ]); return CompleteFormatting(node, link, isReverse); @@ -534,14 +566,14 @@ $('#find-patients').live('pagebeforeshow', function() { - GetResource('/patients?expand&since=0&limit=' + (LIMIT_RESOURCES + 1), function(patients) { + GetResource('/patients?expand&since=0&limit=' + (LIMIT_RESOURCES + 1) + '&full', function(patients) { var target = $('#all-patients'); var count, showAlert, p; $('li', target).remove(); - SortOnDicomTag(patients, 'PatientName', false, false); + SortOnDicomTag(patients, PATIENT_NAME, false, false); if (patients.length <= LIMIT_RESOURCES) { count = patients.length; @@ -579,8 +611,8 @@ $('li', target).remove(); for (var i = 0; i < studies.length; i++) { - patient = studies[i].PatientMainDicomTags.PatientName; - study = studies[i].MainDicomTags.StudyDescription; + patient = GetMainDicomTag(studies[i].PatientMainDicomTags, PATIENT_NAME); + study = GetMainDicomTag(studies[i].MainDicomTags, STUDY_DESCRIPTION); s = ""; if (typeof patient === 'string') { @@ -626,7 +658,7 @@ $('#find-studies').live('pagebeforeshow', function() { - GetResource('/studies?expand&since=0&limit=' + (LIMIT_RESOURCES + 1), function(studies) { + GetResource('/studies?expand&since=0&limit=' + (LIMIT_RESOURCES + 1) + '&full', function(studies) { FormatListOfStudies('#all-studies', '#alert-studies', '#count-studies', studies); }); }); @@ -657,9 +689,9 @@ if ($.mobile.pageData) { pageData = DeepCopy($.mobile.pageData); - GetResource('/patients/' + pageData.uuid, function(patient) { - GetResource('/patients/' + pageData.uuid + '/studies', function(studies) { - SortOnDicomTag(studies, 'StudyDate', false, true); + GetResource('/patients/' + pageData.uuid + '?full', function(patient) { + GetResource('/patients/' + pageData.uuid + '/studies?full', function(studies) { + SortOnDicomTag(studies, STUDY_DATE, false, true); $('#patient-info li').remove(); $('#patient-info') @@ -671,18 +703,20 @@ $('li', target).remove(); for (var i = 0; i < studies.length; i++) { - if (i == 0 || studies[i].MainDicomTags.StudyDate != studies[i - 1].MainDicomTags.StudyDate) + if (i == 0 || + GetMainDicomTag(studies[i].MainDicomTags, STUDY_DATE) != + GetMainDicomTag(studies[i - 1].MainDicomTags, STUDY_DATE)) { target.append($('
  • ') .attr('data-role', 'list-divider') - .text(FormatDicomDate(studies[i].MainDicomTags.StudyDate))); + .text(FormatDicomDate(GetMainDicomTag(studies[i].MainDicomTags, STUDY_DATE)))); } target.append(FormatStudy(studies[i], '#study?uuid=' + studies[i].ID)); } - SetupAnonymizedOrModifiedFrom('#patient-anonymized-from', patient, 'patient', 'AnonymizedFrom'); - SetupAnonymizedOrModifiedFrom('#patient-modified-from', patient, 'patient', 'ModifiedFrom'); + SetupAnonymizedOrModifiedFrom('#patient-anonymized-from', patient, 'patient', ANONYMIZED_FROM); + SetupAnonymizedOrModifiedFrom('#patient-modified-from', patient, 'patient', MODIFIED_FROM); target.listview('refresh'); @@ -714,10 +748,10 @@ if ($.mobile.pageData) { pageData = DeepCopy($.mobile.pageData); - GetResource('/studies/' + pageData.uuid, function(study) { - GetResource('/patients/' + study.ParentPatient, function(patient) { - GetResource('/studies/' + pageData.uuid + '/series', function(series) { - SortOnDicomTag(series, 'SeriesDate', false, true); + GetResource('/studies/' + pageData.uuid + '?full', function(study) { + GetResource('/patients/' + study.ParentPatient + '?full', function(patient) { + GetResource('/studies/' + pageData.uuid + '/series?full', function(series) { + SortOnDicomTag(series, SERIES_DATE, false, true); $('#study .patient-link').attr('href', '#patient?uuid=' + patient.ID); $('#study-info li').remove(); @@ -728,17 +762,19 @@ .append(FormatStudy(study)) .listview('refresh'); - SetupAnonymizedOrModifiedFrom('#study-anonymized-from', study, 'study', 'AnonymizedFrom'); - SetupAnonymizedOrModifiedFrom('#study-modified-from', study, 'study', 'ModifiedFrom'); + SetupAnonymizedOrModifiedFrom('#study-anonymized-from', study, 'study', ANONYMIZED_FROM); + SetupAnonymizedOrModifiedFrom('#study-modified-from', study, 'study', MODIFIED_FROM); target = $('#list-series'); $('li', target).remove(); for (var i = 0; i < series.length; i++) { - if (i == 0 || series[i].MainDicomTags.SeriesDate != series[i - 1].MainDicomTags.SeriesDate) + if (i == 0 || + GetMainDicomTag(series[i].MainDicomTags, SERIES_DATE) != + GetMainDicomTag(series[i - 1].MainDicomTags, SERIES_DATE)) { target.append($('
  • ') .attr('data-role', 'list-divider') - .text(FormatDicomDate(series[i].MainDicomTags.SeriesDate))); + .text(FormatDicomDate(GetMainDicomTag(series[i].MainDicomTags, SERIES_DATE)))); } target.append(FormatSeries(series[i], '#series?uuid=' + series[i].ID)); @@ -761,10 +797,10 @@ if ($.mobile.pageData) { pageData = DeepCopy($.mobile.pageData); - GetResource('/series/' + pageData.uuid, function(series) { - GetResource('/studies/' + series.ParentStudy, function(study) { - GetResource('/patients/' + study.ParentPatient, function(patient) { - GetResource('/series/' + pageData.uuid + '/instances', function(instances) { + GetResource('/series/' + pageData.uuid + '?full', function(series) { + GetResource('/studies/' + series.ParentStudy + '?full', function(study) { + GetResource('/patients/' + study.ParentPatient + '?full', function(patient) { + GetResource('/series/' + pageData.uuid + '/instances?full', function(instances) { Sort(instances, function(x) { return x.IndexInSeries; }, true, false); $('#series .patient-link').attr('href', '#patient?uuid=' + patient.ID); @@ -780,8 +816,8 @@ .append(FormatSeries(series)) .listview('refresh'); - SetupAnonymizedOrModifiedFrom('#series-anonymized-from', series, 'series', 'AnonymizedFrom'); - SetupAnonymizedOrModifiedFrom('#series-modified-from', series, 'series', 'ModifiedFrom'); + SetupAnonymizedOrModifiedFrom('#series-anonymized-from', series, 'series', ANONYMIZED_FROM); + SetupAnonymizedOrModifiedFrom('#series-modified-from', series, 'series', MODIFIED_FROM); target = $('#list-instances'); $('li', target).remove(); @@ -880,10 +916,10 @@ if ($.mobile.pageData) { pageData = DeepCopy($.mobile.pageData); - GetResource('/instances/' + pageData.uuid, function(instance) { - GetResource('/series/' + instance.ParentSeries, function(series) { - GetResource('/studies/' + series.ParentStudy, function(study) { - GetResource('/patients/' + study.ParentPatient, function(patient) { + GetResource('/instances/' + pageData.uuid + '?full', function(instance) { + GetResource('/series/' + instance.ParentSeries + '?full', function(series) { + GetResource('/studies/' + series.ParentStudy + '?full', function(study) { + GetResource('/patients/' + study.ParentPatient + '?full', function(patient) { $('#instance .patient-link').attr('href', '#patient?uuid=' + patient.ID); $('#instance .study-link').attr('href', '#study?uuid=' + study.ID); @@ -918,8 +954,8 @@ } }); - SetupAnonymizedOrModifiedFrom('#instance-anonymized-from', instance, 'instance', 'AnonymizedFrom'); - SetupAnonymizedOrModifiedFrom('#instance-modified-from', instance, 'instance', 'ModifiedFrom'); + SetupAnonymizedOrModifiedFrom('#instance-anonymized-from', instance, 'instance', ANONYMIZED_FROM); + SetupAnonymizedOrModifiedFrom('#instance-modified-from', instance, 'instance', MODIFIED_FROM); currentPage = 'instance'; currentUuid = pageData.uuid; diff -r dd6274412ff4 -r 569d9ef165b1 OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp --- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Thu Jun 17 15:47:21 2021 +0200 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.cpp Fri Jun 18 16:08:35 2021 +0200 @@ -724,16 +724,22 @@ bool StatelessDatabaseOperations::ExpandResource(Json::Value& target, const std::string& publicId, - ResourceType level) + ResourceType level, + DicomToJsonFormat format) { - class Operations : public ReadOnlyOperationsT4 + class Operations : public ReadOnlyOperationsT5< + bool&, Json::Value&, const std::string&, ResourceType, DicomToJsonFormat> { private: static void MainDicomTagsToJson(ReadOnlyTransaction& transaction, Json::Value& target, int64_t resourceId, - ResourceType resourceType) + ResourceType resourceType, + DicomToJsonFormat format) { + static const char* const MAIN_DICOM_TAGS = "MainDicomTags"; + static const char* const PATIENT_MAIN_DICOM_TAGS = "PatientMainDicomTags"; + DicomMap tags; transaction.GetMainDicomTags(tags, resourceId); @@ -743,16 +749,16 @@ tags.ExtractStudyInformation(t1); tags.ExtractPatientInformation(t2); - target["MainDicomTags"] = Json::objectValue; - FromDcmtkBridge::ToJson(target["MainDicomTags"], t1, true); - - target["PatientMainDicomTags"] = Json::objectValue; - FromDcmtkBridge::ToJson(target["PatientMainDicomTags"], t2, true); + target[MAIN_DICOM_TAGS] = Json::objectValue; + FromDcmtkBridge::ToJson(target[MAIN_DICOM_TAGS], t1, format); + + target[PATIENT_MAIN_DICOM_TAGS] = Json::objectValue; + FromDcmtkBridge::ToJson(target[PATIENT_MAIN_DICOM_TAGS], t2, format); } else { - target["MainDicomTags"] = Json::objectValue; - FromDcmtkBridge::ToJson(target["MainDicomTags"], tags, true); + target[MAIN_DICOM_TAGS] = Json::objectValue; + FromDcmtkBridge::ToJson(target[MAIN_DICOM_TAGS], tags, format); } } @@ -949,7 +955,7 @@ // Record the remaining information target["ID"] = tuple.get<2>(); - MainDicomTagsToJson(transaction, target, internalId, type); + MainDicomTagsToJson(transaction, target, internalId, type, tuple.get<4>()); std::string tmp; @@ -982,7 +988,7 @@ bool found; Operations operations; - operations.Apply(*this, found, target, publicId, level); + operations.Apply(*this, found, target, publicId, level, format); return found; } diff -r dd6274412ff4 -r 569d9ef165b1 OrthancServer/Sources/Database/StatelessDatabaseOperations.h --- a/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Thu Jun 17 15:47:21 2021 +0200 +++ b/OrthancServer/Sources/Database/StatelessDatabaseOperations.h Fri Jun 18 16:08:35 2021 +0200 @@ -461,7 +461,8 @@ bool ExpandResource(Json::Value& target, const std::string& publicId, - ResourceType level); + ResourceType level, + DicomToJsonFormat format); void GetAllMetadata(std::map& target, const std::string& publicId, diff -r dd6274412ff4 -r 569d9ef165b1 OrthancServer/Sources/LuaScripting.cpp --- a/OrthancServer/Sources/LuaScripting.cpp Thu Jun 17 15:47:21 2021 +0200 +++ b/OrthancServer/Sources/LuaScripting.cpp Fri Jun 18 16:08:35 2021 +0200 @@ -182,11 +182,11 @@ { DicomMap t; tags_.ExtractStudyInformation(t); // Discard patient-related tags - FromDcmtkBridge::ToJson(json, t, true); + FromDcmtkBridge::ToJson(json, t, DicomToJsonFormat_Human); } else { - FromDcmtkBridge::ToJson(json, tags_, true); + FromDcmtkBridge::ToJson(json, tags_, DicomToJsonFormat_Human); } LuaFunctionCall call(lock.GetLua(), name); diff -r dd6274412ff4 -r 569d9ef165b1 OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp Thu Jun 17 15:47:21 2021 +0200 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.cpp Fri Jun 18 16:08:35 2021 +0200 @@ -460,4 +460,117 @@ .SetRequestField(KEY_PERMISSIVE, RestApiCallDocumentation::Type_Boolean, "If `true`, ignore errors during the individual steps of the job.", false); } + + + static const std::string GET_SIMPLIFY = "simplify"; + static const std::string GET_FULL = "full"; + static const std::string GET_SHORT = "short"; + + static const std::string POST_SIMPLIFY = "Simplify"; + static const std::string POST_FULL = "Full"; + static const std::string POST_SHORT = "Short"; + + static const std::string DOCUMENT_SIMPLIFY = + "report the DICOM tags indexed in human-readable format " + "(using the symbolic name of the tags)"; + + static const std::string DOCUMENT_SHORT = + "report the DICOM tags indexed in hexadecimal format"; + + static const std::string DOCUMENT_FULL = + "report the DICOM tags in full format (tags indexed by their hexadecimal " + "format, associated with their symbolic name and their value)"; + + + DicomToJsonFormat OrthancRestApi::GetDicomFormat(const RestApiGetCall& call, + DicomToJsonFormat defaultFormat) + { + if (call.HasArgument(GET_SIMPLIFY)) + { + return DicomToJsonFormat_Human; + } + else if (call.HasArgument(GET_SHORT)) + { + return DicomToJsonFormat_Short; + } + else if (call.HasArgument(GET_FULL)) + { + return DicomToJsonFormat_Full; + } + else + { + return defaultFormat; + } + } + + + DicomToJsonFormat OrthancRestApi::GetDicomFormat(const Json::Value& body, + DicomToJsonFormat defaultFormat) + { + if (body.isMember(POST_SIMPLIFY) && + SerializationToolbox::ReadBoolean(body, POST_SIMPLIFY)) + { + return DicomToJsonFormat_Human; + } + else if (body.isMember(POST_SHORT) && + SerializationToolbox::ReadBoolean(body, POST_SHORT)) + { + return DicomToJsonFormat_Short; + } + else if (body.isMember(POST_FULL) && + SerializationToolbox::ReadBoolean(body, POST_FULL)) + { + return DicomToJsonFormat_Full; + } + else + { + return defaultFormat; + } + } + + + void OrthancRestApi::DocumentDicomFormat(RestApiGetCall& call, + DicomToJsonFormat defaultFormat) + { + if (defaultFormat != DicomToJsonFormat_Human) + { + call.GetDocumentation().SetHttpGetArgument( + GET_SIMPLIFY, RestApiCallDocumentation::Type_Boolean, "If present, " + DOCUMENT_SIMPLIFY, false); + } + + if (defaultFormat != DicomToJsonFormat_Short) + { + call.GetDocumentation().SetHttpGetArgument( + GET_SHORT, RestApiCallDocumentation::Type_Boolean, "If present, " + DOCUMENT_SHORT, false); + } + + if (defaultFormat != DicomToJsonFormat_Full) + { + call.GetDocumentation().SetHttpGetArgument( + GET_FULL, RestApiCallDocumentation::Type_Boolean, "If present, " + DOCUMENT_FULL, false); + } + } + + + void OrthancRestApi::DocumentDicomFormat(RestApiPostCall& call, + DicomToJsonFormat defaultFormat) + { + if (defaultFormat != DicomToJsonFormat_Human) + { + call.GetDocumentation().SetRequestField(POST_SIMPLIFY, RestApiCallDocumentation::Type_Boolean, + "If set to `true`, " + DOCUMENT_SIMPLIFY, false); + } + + if (defaultFormat != DicomToJsonFormat_Short) + { + call.GetDocumentation().SetRequestField(POST_SHORT, RestApiCallDocumentation::Type_Boolean, + "If set to `true`, " + DOCUMENT_SIMPLIFY, false); + } + + if (defaultFormat != DicomToJsonFormat_Full) + { + call.GetDocumentation().SetRequestField(POST_FULL, RestApiCallDocumentation::Type_Boolean, + "If set to `true`, " + DOCUMENT_SIMPLIFY, false); + } + } } diff -r dd6274412ff4 -r 569d9ef165b1 OrthancServer/Sources/OrthancRestApi/OrthancRestApi.h --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.h Thu Jun 17 15:47:21 2021 +0200 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestApi.h Fri Jun 18 16:08:35 2021 +0200 @@ -144,5 +144,17 @@ static void DocumentSubmitGenericJob(RestApiPostCall& call); static void DocumentSubmitCommandsJob(RestApiPostCall& call); + + static DicomToJsonFormat GetDicomFormat(const RestApiGetCall& call, + DicomToJsonFormat defaultFormat); + + static DicomToJsonFormat GetDicomFormat(const Json::Value& body, + DicomToJsonFormat defaultFormat); + + static void DocumentDicomFormat(RestApiGetCall& call, + DicomToJsonFormat defaultFormat); + + static void DocumentDicomFormat(RestApiPostCall& call, + DicomToJsonFormat defaultFormat); }; } diff -r dd6274412ff4 -r 569d9ef165b1 OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp Thu Jun 17 15:47:21 2021 +0200 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestModalities.cpp Fri Jun 18 16:08:35 2021 +0200 @@ -819,12 +819,12 @@ } }; - static void AnswerDicomMap(RestApiCall& call, + static void AnswerDicomMap(RestApiGetCall& call, const DicomMap& value, - bool simplify) + DicomToJsonFormat format) { Json::Value full = Json::objectValue; - FromDcmtkBridge::ToJson(full, value, simplify); + FromDcmtkBridge::ToJson(full, value, format); call.GetOutput().AnswerJson(full); } } @@ -834,6 +834,8 @@ { if (call.IsDocumentation()) { + OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); + call.GetDocumentation() .SetTag("Networking") .SetSummary("List answers to a query") @@ -842,15 +844,13 @@ .SetUriArgument("id", "Identifier of the query of interest") .SetHttpGetArgument("expand", RestApiCallDocumentation::Type_String, "If present, retrieve detailed information about the individual answers", false) - .SetHttpGetArgument("simplify", RestApiCallDocumentation::Type_String, - "If present and if `expand` is present, format the tags of the answers in human-readable format", false) .AddAnswerType(MimeType_Json, "JSON array containing the indices of the answers, or detailed information " "about the reported answers (if `expand` argument is provided)"); return; } const bool expand = call.HasArgument("expand"); - const bool simplify = call.HasArgument("simplify"); + const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full); QueryAccessor query(call); size_t count = query.GetHandler().GetAnswersCount(); @@ -865,7 +865,7 @@ query.GetHandler().GetAnswer(value, i); Json::Value json = Json::objectValue; - FromDcmtkBridge::ToJson(json, value, simplify); + FromDcmtkBridge::ToJson(json, value, format); result.append(json); } @@ -883,6 +883,8 @@ { if (call.IsDocumentation()) { + OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); + call.GetDocumentation() .SetTag("Networking") .SetSummary("Get one answer") @@ -890,8 +892,6 @@ "query/retrieve operation whose identifier is provided in the URL") .SetUriArgument("id", "Identifier of the query of interest") .SetUriArgument("index", "Index of the answer") - .SetHttpGetArgument("simplify", RestApiCallDocumentation::Type_String, - "If present, format the tags of the answer in human-readable format", false) .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags of the answer"); return; } @@ -903,7 +903,7 @@ DicomMap map; query.GetHandler().GetAnswer(map, index); - AnswerDicomMap(call, map, call.HasArgument("simplify")); + AnswerDicomMap(call, map, OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full)); } @@ -1031,6 +1031,8 @@ { if (call.IsDocumentation()) { + OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); + call.GetDocumentation() .SetTag("Networking") .SetSummary("Get original query arguments") @@ -1044,7 +1046,7 @@ } QueryAccessor query(call); - AnswerDicomMap(call, query.GetHandler().GetQuery(), call.HasArgument("simplify")); + AnswerDicomMap(call, query.GetHandler().GetQuery(), OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full)); } diff -r dd6274412ff4 -r 569d9ef165b1 OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp --- a/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Thu Jun 17 15:47:21 2021 +0200 +++ b/OrthancServer/Sources/OrthancRestApi/OrthancRestResources.cpp Fri Jun 18 16:08:35 2021 +0200 @@ -112,30 +112,6 @@ } - static DicomToJsonFormat GetDicomFormat(const RestApiGetCall& call) - { - if (call.HasArgument("simplify")) - { - return DicomToJsonFormat_Human; - } - else if (call.HasArgument("short")) - { - return DicomToJsonFormat_Short; - } - else - { - return DicomToJsonFormat_Full; - } - } - - - static void AnswerDicomAsJson(RestApiGetCall& call, - const Json::Value& dicom) - { - AnswerDicomAsJson(call, dicom, GetDicomFormat(call)); - } - - static void ParseSetOfTags(std::set& target, const RestApiGetCall& call, const std::string& argument) @@ -161,7 +137,8 @@ ServerIndex& index, const std::list& resources, ResourceType level, - bool expand) + bool expand, + DicomToJsonFormat format) { Json::Value answer = Json::arrayValue; @@ -171,7 +148,7 @@ if (expand) { Json::Value expanded; - if (index.ExpandResource(expanded, *resource, level)) + if (index.ExpandResource(expanded, *resource, level, format)) { answer.append(expanded); } @@ -191,6 +168,8 @@ { if (call.IsDocumentation()) { + OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human); + const std::string resources = GetResourceTypeText(resourceType, true /* plural */, false /* lower case */); call.GetDocumentation() .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */)) @@ -236,8 +215,8 @@ index.GetAllUuids(result, resourceType); } - - AnswerListOfResources(call.GetOutput(), index, result, resourceType, call.HasArgument("expand")); + AnswerListOfResources(call.GetOutput(), index, result, resourceType, call.HasArgument("expand"), + OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human)); } @@ -247,6 +226,8 @@ { if (call.IsDocumentation()) { + OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human); + const std::string resource = GetResourceTypeText(resourceType, false /* plural */, false /* lower case */); call.GetDocumentation() .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */)) @@ -258,8 +239,11 @@ return; } + const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human); + Json::Value json; - if (OrthancRestApi::GetIndex(call).ExpandResource(json, call.GetUriComponent("id", ""), resourceType)) + if (OrthancRestApi::GetIndex(call).ExpandResource( + json, call.GetUriComponent("id", ""), resourceType, format)) { call.GetOutput().AnswerJson(json); } @@ -421,29 +405,8 @@ template - static void GetInstanceTags(RestApiGetCall& call) + static void GetInstanceTagsInternal(RestApiGetCall& call) { - if (call.IsDocumentation()) - { - if (format == DicomToJsonFormat_Human) - { - call.GetDocumentation() - .SetTag("Instances") - .SetSummary("Get human-readable tags") - .SetDescription("Get the DICOM tags in human-readable format") - .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest") - .SetHttpGetArgument("ignore-length", RestApiCallDocumentation::Type_JsonListOfStrings, - "Also include the DICOM tags that are provided in this list, even if their associated value is long", false) - .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value") - .SetTruncatedJsonHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/simplified-tags", 10); - return; - } - else - { - throw OrthancException(ErrorCode_NotImplemented); - } - } - ServerContext& context = OrthancRestApi::GetContext(call); std::string publicId = call.GetUriComponent("id", ""); @@ -470,38 +433,34 @@ } - static void GetInstanceTagsBis(RestApiGetCall& call) + static void GetInstanceTags(RestApiGetCall& call) { if (call.IsDocumentation()) { + OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); call.GetDocumentation() .SetTag("Instances") .SetSummary("Get DICOM tags") .SetDescription("Get the DICOM tags in the specified format. By default, the `full` format is used, which " "combines hexadecimal tags with human-readable description.") .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest") - .SetHttpGetArgument("simplify", RestApiCallDocumentation::Type_String, - "If present, report the DICOM tags in human-readable format " - "(same as the `/instances/{id}/simplified-tags` route)", false) - .SetHttpGetArgument("short", RestApiCallDocumentation::Type_String, - "If present, report the DICOM tags indexed in hexadecimal format", false) .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value") .SetTruncatedJsonHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/tags", 10); return; } - switch (GetDicomFormat(call)) + switch (OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full)) { case DicomToJsonFormat_Human: - GetInstanceTags(call); + GetInstanceTagsInternal(call); break; case DicomToJsonFormat_Short: - GetInstanceTags(call); + GetInstanceTagsInternal(call); break; case DicomToJsonFormat_Full: - GetInstanceTags(call); + GetInstanceTagsInternal(call); break; default: @@ -510,6 +469,28 @@ } + static void GetInstanceSimplifiedTags(RestApiGetCall& call) + { + if (call.IsDocumentation()) + { + call.GetDocumentation() + .SetTag("Instances") + .SetSummary("Get human-readable tags") + .SetDescription("Get the DICOM tags in human-readable format (same as the `/instances/{id}/tags?simplify` route)") + .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest") + .SetHttpGetArgument("ignore-length", RestApiCallDocumentation::Type_JsonListOfStrings, + "Also include the DICOM tags that are provided in this list, even if their associated value is long", false) + .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value") + .SetTruncatedJsonHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/simplified-tags", 10); + return; + } + else + { + GetInstanceTagsInternal(call); + } + } + + static void ListFrames(RestApiGetCall& call) { if (call.IsDocumentation()) @@ -2367,6 +2348,8 @@ { if (call.IsDocumentation()) { + OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); + ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); call.GetDocumentation() @@ -2387,15 +2370,51 @@ if (ExtractSharedTags(sharedTags, context, publicId)) { // Success: Send the value of the shared tags - AnswerDicomAsJson(call, sharedTags); + AnswerDicomAsJson(call, sharedTags, OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full)); } } - static void GetModuleInternal(RestApiGetCall& call, - ResourceType resourceType, - DicomModule module) + template + static void GetModule(RestApiGetCall& call) { + if (call.IsDocumentation()) + { + const std::string resource = GetResourceTypeText(resourceType, false /* plural */, false /* lower case */); + std::string m; + switch (module) + { + case DicomModule_Patient: + m = "patient"; + break; + case DicomModule_Study: + m = "study"; + break; + case DicomModule_Series: + m = "series"; + break; + case DicomModule_Instance: + m = "instance"; + break; + default: + throw OrthancException(ErrorCode_ParameterOutOfRange); + } + + OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); + + call.GetDocumentation() + .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */)) + .SetSummary("Get " + m + " module" + std::string(resource == m ? "" : " of " + resource)) + .SetDescription("Get the " + m + " module of the DICOM " + resource + " whose Orthanc identifier is provided in the URL") + .SetUriArgument("id", "Orthanc identifier of the " + resource + " of interest") + .SetHttpGetArgument("ignore-length", RestApiCallDocumentation::Type_JsonListOfStrings, + "Also include the DICOM tags that are provided in this list, even if their associated value is long", false) + .AddAnswerType(MimeType_Json, "Information about the DICOM " + resource) + .SetHttpGetSample(GetDocumentationSampleResource(resourceType) + "/" + (*call.GetFullUri().rbegin()), true); + return; + } + if (!((resourceType == ResourceType_Patient && module == DicomModule_Patient) || (resourceType == ResourceType_Study && module == DicomModule_Patient) || (resourceType == ResourceType_Study && module == DicomModule_Study) || @@ -2447,49 +2466,7 @@ } } - AnswerDicomAsJson(call, result); - } - - - - template - static void GetModule(RestApiGetCall& call) - { - if (call.IsDocumentation()) - { - const std::string resource = GetResourceTypeText(resourceType, false /* plural */, false /* lower case */); - std::string m; - switch (module) - { - case DicomModule_Patient: - m = "patient"; - break; - case DicomModule_Study: - m = "study"; - break; - case DicomModule_Series: - m = "series"; - break; - case DicomModule_Instance: - m = "instance"; - break; - default: - throw OrthancException(ErrorCode_ParameterOutOfRange); - } - call.GetDocumentation() - .SetTag(GetResourceTypeText(resourceType, true /* plural */, true /* upper case */)) - .SetSummary("Get " + m + " module" + std::string(resource == m ? "" : " of " + resource)) - .SetDescription("Get the " + m + " module of the DICOM " + resource + " whose Orthanc identifier is provided in the URL") - .SetUriArgument("id", "Orthanc identifier of the " + resource + " of interest") - .SetHttpGetArgument("ignore-length", RestApiCallDocumentation::Type_JsonListOfStrings, - "Also include the DICOM tags that are provided in this list, even if their associated value is long", false) - .AddAnswerType(MimeType_Json, "Information about the DICOM " + resource) - .SetHttpGetSample(GetDocumentationSampleResource(resourceType) + "/" + (*call.GetFullUri().rbegin()), true); - return; - } - - GetModuleInternal(call, resourceType, module); + AnswerDicomAsJson(call, result, OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full)); } @@ -2567,10 +2544,12 @@ private: bool isComplete_; std::list resources_; + DicomToJsonFormat format_; public: - FindVisitor() : - isComplete_(false) + FindVisitor(DicomToJsonFormat format) : + isComplete_(false), + format_(format) { } @@ -2597,7 +2576,7 @@ ResourceType level, bool expand) const { - AnswerListOfResources(output, index, resources_, level, expand); + AnswerListOfResources(output, index, resources_, level, expand, format_); } }; } @@ -2614,6 +2593,8 @@ if (call.IsDocumentation()) { + OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human); + call.GetDocumentation() .SetTag("System") .SetSummary("Look for local resources") @@ -2741,7 +2722,7 @@ } } - FindVisitor visitor; + FindVisitor visitor(OrthancRestApi::GetDicomFormat(request, DicomToJsonFormat_Human)); context.Apply(visitor, query, level, since, limit); visitor.Answer(call.GetOutput(), context.GetIndex(), level, expand); } @@ -2754,6 +2735,8 @@ { if (call.IsDocumentation()) { + OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human); + const std::string children = GetResourceTypeText(end, true /* plural */, false /* lower case */); const std::string resource = GetResourceTypeText(start, false /* plural */, false /* lower case */); call.GetDocumentation() @@ -2792,11 +2775,13 @@ Json::Value result = Json::arrayValue; + const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human); + for (std::list::const_iterator it = a.begin(); it != a.end(); ++it) { Json::Value resource; - if (OrthancRestApi::GetIndex(call).ExpandResource(resource, *it, end)) + if (OrthancRestApi::GetIndex(call).ExpandResource(resource, *it, end, format)) { result.append(resource); } @@ -2810,6 +2795,8 @@ { if (call.IsDocumentation()) { + OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); + ResourceType t = StringToResourceType(call.GetFullUri()[0].c_str()); std::string r = GetResourceTypeText(t, false /* plural */, false /* upper case */); call.GetDocumentation() @@ -2827,7 +2814,7 @@ ServerContext& context = OrthancRestApi::GetContext(call); std::string publicId = call.GetUriComponent("id", ""); - DicomToJsonFormat format = GetDicomFormat(call); + DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full); std::set ignoreTagLength; ParseSetOfTags(ignoreTagLength, call, "ignore-length"); @@ -2871,6 +2858,8 @@ if (call.IsDocumentation()) { + OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Human); + const std::string parent = GetResourceTypeText(end, false /* plural */, false /* lower case */); const std::string resource = GetResourceTypeText(start, false /* plural */, false /* lower case */); call.GetDocumentation() @@ -2904,8 +2893,10 @@ assert(currentType == end); + const DicomToJsonFormat format = OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Human); + Json::Value resource; - if (OrthancRestApi::GetIndex(call).ExpandResource(resource, current, end)) + if (OrthancRestApi::GetIndex(call).ExpandResource(resource, current, end, format)) { call.GetOutput().AnswerJson(resource); } @@ -2978,16 +2969,13 @@ { if (call.IsDocumentation()) { + OrthancRestApi::DocumentDicomFormat(call, DicomToJsonFormat_Full); call.GetDocumentation() .SetTag("Instances") .SetSummary("Get DICOM meta-header") .SetDescription("Get the DICOM tags in the meta-header of the DICOM instance. By default, the `full` format is used, which " "combines hexadecimal tags with human-readable description.") .SetUriArgument("id", "Orthanc identifier of the DICOM instance of interest") - .SetHttpGetArgument("simplify", RestApiCallDocumentation::Type_String, - "If present, report the DICOM tags in human-readable format", false) - .SetHttpGetArgument("short", RestApiCallDocumentation::Type_String, - "If present, report the DICOM tags indexed in hexadecimal format", false) .AddAnswerType(MimeType_Json, "JSON object containing the DICOM tags and their associated value") .SetHttpGetSample("https://demo.orthanc-server.com/instances/7c92ce8e-bbf67ed2-ffa3b8c1-a3b35d94-7ff3ae26/header", true); return; @@ -3008,7 +2996,7 @@ Json::Value header; OrthancConfiguration::DefaultDicomHeaderToJson(header, dicom); - AnswerDicomAsJson(call, header); + AnswerDicomAsJson(call, header, OrthancRestApi::GetDicomFormat(call, DicomToJsonFormat_Full)); } @@ -3183,8 +3171,8 @@ Register("/instances/{id}/file", GetInstanceFile); Register("/instances/{id}/export", ExportInstanceFile); - Register("/instances/{id}/tags", GetInstanceTagsBis); - Register("/instances/{id}/simplified-tags", GetInstanceTags); + Register("/instances/{id}/tags", GetInstanceTags); + Register("/instances/{id}/simplified-tags", GetInstanceSimplifiedTags); Register("/instances/{id}/frames", ListFrames); Register("/instances/{id}/frames/{frame}", RestApi::AutoListChildren); diff -r dd6274412ff4 -r 569d9ef165b1 OrthancServer/Sources/OrthancWebDav.cpp --- a/OrthancServer/Sources/OrthancWebDav.cpp Thu Jun 17 15:47:21 2021 +0200 +++ b/OrthancServer/Sources/OrthancWebDav.cpp Fri Jun 18 16:08:35 2021 +0200 @@ -270,7 +270,7 @@ const Json::Value* dicomAsJson /* unused (*) */) ORTHANC_OVERRIDE { Json::Value resource; - if (context_.GetIndex().ExpandResource(resource, publicId, level_)) + if (context_.GetIndex().ExpandResource(resource, publicId, level_, DicomToJsonFormat_Human)) { if (success_) {