Coverage Report

Created: 2026-01-17 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/behaviortreecpp/src/json_export.cpp
Line
Count
Source
1
#include "behaviortree_cpp/json_export.h"
2
3
namespace BT
4
{
5
6
JsonExporter& JsonExporter::get()
7
1.05M
{
8
1.05M
  static JsonExporter global_instance;
9
1.05M
  return global_instance;
10
1.05M
}
11
12
bool JsonExporter::toJson(const Any& any, nlohmann::json& dst) const
13
544k
{
14
544k
  auto const& type = any.castedType();
15
16
544k
  if(any.isString())
17
36.2k
  {
18
36.2k
    dst = any.cast<std::string>();
19
36.2k
  }
20
508k
  else if(type == typeid(int64_t))
21
379k
  {
22
379k
    dst = any.cast<int64_t>();
23
379k
  }
24
128k
  else if(type == typeid(uint64_t))
25
2.72k
  {
26
2.72k
    dst = any.cast<uint64_t>();
27
2.72k
  }
28
126k
  else if(type == typeid(double))
29
103k
  {
30
103k
    dst = any.cast<double>();
31
103k
  }
32
22.5k
  else if(type == typeid(std::vector<double>))
33
2.37k
  {
34
2.37k
    dst = any.cast<std::vector<double>>();
35
2.37k
  }
36
20.1k
  else if(type == typeid(std::vector<int>))
37
3.52k
  {
38
3.52k
    dst = any.cast<std::vector<int>>();
39
3.52k
  }
40
16.6k
  else if(type == typeid(std::vector<std::string>))
41
3.01k
  {
42
3.01k
    dst = any.cast<std::vector<std::string>>();
43
3.01k
  }
44
13.6k
  else if(type == typeid(std::vector<bool>))
45
12.0k
  {
46
12.0k
    dst = any.cast<std::vector<bool>>();
47
12.0k
  }
48
1.58k
  else
49
1.58k
  {
50
1.58k
    auto it = to_json_converters_.find(type);
51
1.58k
    if(it != to_json_converters_.end())
52
0
    {
53
0
      it->second(any, dst);
54
0
    }
55
1.58k
    else
56
1.58k
    {
57
1.58k
      return false;
58
1.58k
    }
59
1.58k
  }
60
542k
  return true;
61
544k
}
62
63
JsonExporter::ExpectedEntry JsonExporter::fromJson(const nlohmann::json& source) const
64
508k
{
65
508k
  if(source.is_null())
66
1.54k
  {
67
1.54k
    return Entry{ BT::Any(), BT::TypeInfo::Create<std::nullptr_t>() };
68
1.54k
  }
69
70
506k
  if(source.is_string())
71
21.3k
  {
72
21.3k
    return Entry{ BT::Any(source.get<std::string>()),
73
21.3k
                  BT::TypeInfo::Create<std::string>() };
74
21.3k
  }
75
485k
  if(source.is_number_integer())
76
365k
  {
77
365k
    return Entry{ BT::Any(source.get<int>()), BT::TypeInfo::Create<int>() };
78
365k
  }
79
119k
  if(source.is_number_float())
80
97.3k
  {
81
97.3k
    return Entry{ BT::Any(source.get<double>()), BT::TypeInfo::Create<double>() };
82
97.3k
  }
83
22.5k
  if(source.is_boolean())
84
82
  {
85
82
    return Entry{ BT::Any(source.get<bool>()), BT::TypeInfo::Create<bool>() };
86
82
  }
87
88
  // basic vectors
89
22.4k
  if(source.is_array() && source.size() > 0 && !source.contains("__type"))
90
19.4k
  {
91
19.4k
    const auto first_element = source[0];
92
19.4k
    if(first_element.is_string())
93
3.08k
    {
94
3.08k
      return Entry{ BT::Any(source.get<std::vector<std::string>>()),
95
3.08k
                    BT::TypeInfo::Create<std::vector<std::string>>() };
96
3.08k
    }
97
16.3k
    if(first_element.is_number_integer())
98
3.35k
    {
99
3.35k
      return Entry{ BT::Any(source.get<std::vector<int>>()),
100
3.35k
                    BT::TypeInfo::Create<std::vector<int>>() };
101
3.35k
    }
102
12.9k
    if(first_element.is_number_float())
103
1.88k
    {
104
1.88k
      return Entry{ BT::Any(source.get<std::vector<double>>()),
105
1.88k
                    BT::TypeInfo::Create<std::vector<double>>() };
106
1.88k
    }
107
11.0k
    if(first_element.is_boolean())
108
10.1k
    {
109
10.1k
      return Entry{ BT::Any(source.get<std::vector<bool>>()),
110
10.1k
                    BT::TypeInfo::Create<std::vector<bool>>() };
111
10.1k
    }
112
11.0k
  }
113
114
4.06k
  if(source.is_array())
115
2.82k
  {
116
2.82k
    if(source.empty())
117
1.83k
      return nonstd::make_unexpected("Missing field '__type'");
118
985
    const auto& first = source[0];
119
985
    if(!first.is_object() || !first.contains("__type"))
120
871
      return nonstd::make_unexpected("Missing field '__type'");
121
114
    if(!first["__type"].is_string())
122
76
      return nonstd::make_unexpected("Invalid '__type' (must be string)");
123
114
  }
124
1.24k
  else
125
1.24k
  {
126
1.24k
    if(!source.is_object() || !source.contains("__type") || !source["__type"].is_string())
127
589
      return nonstd::make_unexpected("Missing field '__type'");
128
1.24k
  }
129
130
695
  auto& from_converters =
131
695
      source.is_array() ? from_json_array_converters_ : from_json_converters_;
132
695
  auto type_field = source.is_array() ? source[0]["__type"] : source["__type"];
133
134
695
  auto type_it = type_names_.find(type_field);
135
695
  if(type_it == type_names_.end())
136
695
  {
137
695
    return nonstd::make_unexpected("Type not found in registered list");
138
695
  }
139
0
  auto func_it = from_converters.find(type_it->second.type());
140
0
  if(func_it == from_converters.end())
141
0
  {
142
0
    return nonstd::make_unexpected("Type not found in registered list");
143
0
  }
144
0
  return func_it->second(source);
145
0
}
146
147
JsonExporter::ExpectedEntry JsonExporter::fromJson(const nlohmann::json& source,
148
                                                   std::type_index type) const
149
0
{
150
0
  auto func_it = from_json_converters_.find(type);
151
0
  if(func_it == from_json_converters_.end())
152
0
  {
153
0
    return nonstd::make_unexpected("Type not found in registered list");
154
0
  }
155
0
  return func_it->second(source);
156
0
}
157
158
}  // namespace BT