@@ -352,7 +352,7 @@ class UserAttributes {
352352 * @endcode
353353 */
354354 UserAttributes (const UserAttributes& other)
355- : stats(other.stats), attrs(other.attrs) {}
355+ : stats(other.stats), units(other.units), attrs(other.attrs) {}
356356
357357 /* *
358358 * @brief Constructs a UserAttributes object from a JSON representation of a
@@ -410,35 +410,60 @@ class UserAttributes {
410410 // Because the user can supply JSON here, there's a chance that the JSON is
411411 // malformed.
412412 try {
413- if (j.contains (" statsV1" )) {
414- auto statsJson = j[" statsV1" ];
413+ if (j.contains (" statsV1" ) || j.contains (" unitsV1" )) {
415414 std::vector<internal::SummaryStats> statsCollection;
416- if (statsJson.is_array ()) {
417- for (auto & s : statsJson) {
418- auto statsRes = internal::SummaryStats::FromJson<T>(s);
415+ if (j.contains (" statsV1" )) {
416+ auto statsJson = j[" statsV1" ];
417+ if (statsJson.is_array ()) {
418+ for (auto & s : statsJson) {
419+ auto statsRes = internal::SummaryStats::FromJson<T>(s);
420+ if (!statsRes.status ().ok ()) {
421+ return statsRes.status ();
422+ }
423+ statsCollection.emplace_back (statsRes.value ());
424+ }
425+ } else {
426+ auto statsRes = internal::SummaryStats::FromJson<T>(statsJson);
419427 if (!statsRes.status ().ok ()) {
420428 return statsRes.status ();
421429 }
422430 statsCollection.emplace_back (statsRes.value ());
423431 }
424- } else {
425- auto statsRes = internal::SummaryStats::FromJson<T>(statsJson);
426- if (!statsRes.status ().ok ()) {
427- return statsRes.status ();
432+ }
433+ std::vector<std::string> unitsCollection;
434+ if (j.contains (" unitsV1" )) {
435+ auto unitsJson = j[" unitsV1" ];
436+ if (unitsJson.is_array ()) {
437+ for (auto & s : unitsJson) {
438+ if (s.is_object ()) {
439+ // If the element is an object, iterate its key-value pairs.
440+ for (auto & kv : s.items ()) {
441+ unitsCollection.push_back (kv.value ().get <std::string>());
442+ }
443+ } else {
444+ unitsCollection.push_back (s.get <std::string>());
445+ }
446+ }
447+ } else if (unitsJson.is_object ()) {
448+ // If unitsV1 itself is an object, iterate its key-value pairs.
449+ for (auto & kv : unitsJson.items ()) {
450+ unitsCollection.push_back (kv.value ().get <std::string>());
451+ }
452+ } else {
453+ unitsCollection.push_back (unitsJson.get <std::string>());
428454 }
429- statsCollection.emplace_back (statsRes.value ());
430455 }
431456 auto attrs =
432- UserAttributes (statsCollection, j. contains ( " attributes " )
433- ? j[" attributes" ]
434- : nlohmann::json::object ());
435- return attrs;
457+ UserAttributes (statsCollection, unitsCollection,
458+ j. contains ( " attributes " ) ? j[" attributes" ]
459+ : nlohmann::json::object ());
460+ return mdio::Result<UserAttributes>( attrs) ;
436461 } else if (j.contains (" attributes" )) {
437462 auto attrs = UserAttributes (j[" attributes" ]);
438- return attrs;
463+ return mdio::Result<UserAttributes>( attrs) ;
439464 }
440465 auto attrs = UserAttributes (nlohmann::json::object ());
441- return attrs;
466+ return mdio::Result<UserAttributes>( attrs) ;
442467 } catch (const nlohmann::json::exception& e) {
443468 return absl::InvalidArgumentError (
444469 " There appeared to be some malformed JSON" + std::string (e.what ()));
@@ -454,6 +479,12 @@ class UserAttributes {
454479 */
455480 const nlohmann::json getStatsV1 () const { return statsBindable (); }
456481
482+ /* *
483+ * @brief Extracts just the unitsV1 JSON
484+ * @return The unitsV1 JSON representation of the data
485+ */
486+ const nlohmann::json getUnitsV1 () const { return unitsBindable (); }
487+
457488 /* *
458489 * @brief Extracts just the attributes JSON
459490 * @return The attributes JSON representation of the data
@@ -469,6 +500,9 @@ class UserAttributes {
469500 if (stats.size () >= 1 ) {
470501 j[" statsV1" ] = statsBindable ();
471502 }
503+ if (units.size () >= 1 ) {
504+ j[" unitsV1" ] = unitsBindable ();
505+ }
472506 auto attrs = attrsBindable ();
473507 if (attrs.empty ()) {
474508 return j;
@@ -485,7 +519,7 @@ class UserAttributes {
485519 * static member function `FromJson(nlohmann::json)`
486520 */
487521 explicit UserAttributes (const nlohmann::json& attrs)
488- : attrs(attrs), stats({}) {}
522+ : attrs(attrs), stats({}), units({}) {}
489523
490524 /* *
491525 * @brief A case where there are statsV1 objects but no attributes
@@ -494,10 +528,33 @@ class UserAttributes {
494528 * @note This constructor is intended for internal use only. Please use the
495529 * static member function `FromJson(nlohmann::json)`
496530 */
531+ UserAttributes (const std::vector<internal::SummaryStats>& stats,
532+ const nlohmann::json attrs)
533+ : stats(stats), units({}), attrs(attrs) {}
534+
535+ /* *
536+ * @brief A case where there are unitsV1 objects but no attributes
537+ * @param units A collection of SummaryStats objects
538+ * @param attrs User specified attributes
539+ * @note This constructor is intended for internal use only. Please use the
540+ * static member function `FromJson(nlohmann::json)`
541+ */
542+ UserAttributes (const std::vector<std::string>& units,
543+ const nlohmann::json attrs)
544+ : units(units), attrs(attrs) {}
497545
546+ /* *
547+ * @brief A case where there are both statsV1 and unitsV1 objects
548+ * @param stats A collection of SummaryStats objects
549+ * @param units A collection of SummaryStats objects
550+ * @param attrs User specified attributes
551+ * @note This constructor is intended for internal use only. Please use the
552+ * static member function `FromJson(nlohmann::json)`
553+ */
498554 UserAttributes (const std::vector<internal::SummaryStats>& stats,
555+ const std::vector<std::string>& units,
499556 const nlohmann::json attrs)
500- : stats(stats), attrs(attrs) {}
557+ : stats(stats), units(units), attrs(attrs) {}
501558
502559 /* *
503560 * @brief Binds the existing statsV1 data to a JSON object
@@ -516,6 +573,23 @@ class UserAttributes {
516573 return statsRet;
517574 }
518575
576+ /* *
577+ * @brief Binds the existing unitsV1 data to a JSON object
578+ * @return A bindable unitsV1 JSON object
579+ */
580+ const nlohmann::json unitsBindable () const {
581+ if (units.empty ()) {
582+ return nlohmann::json::object ();
583+ } else if (units.size () == 1 ) {
584+ return units[0 ];
585+ }
586+ nlohmann::json unitsRet = nlohmann::json::array ();
587+ for (const auto & unit : units) {
588+ unitsRet.push_back (unit);
589+ }
590+ return unitsRet;
591+ }
592+
519593 /* *
520594 * @brief Binds the existing attributes data to a JSON object
521595 * @return A bindable attributes JSON object
@@ -547,13 +621,14 @@ class UserAttributes {
547621 return true ; // Assumption #1
548622 }
549623 }
550- return false ; // If we get here then we have only integers
624+ return false ;
551625 }
552626 }
553- return true ; // We don't care, a histogram doesn't exist in this Variable
627+ return true ; // Default to float if no histogram is provided
554628 }
555629
556630 std::vector<internal::SummaryStats> stats;
631+ std::vector<std::string> units;
557632 const nlohmann::json attrs;
558633};
559634
0 commit comments