83 {
84
85#if FASTLED_NO_JSON
89 FL_WARN(
"ScreenMap::ParseJson called with FASTLED_NO_JSON");
90 if (err) {
91 *err = "JSON is not supported in this build";
92 }
93 return false;
94#else
95
96
97 string _err;
98 if (!err) {
99 err = &_err;
100 }
101
103 if (!jsonDoc.has_value()) {
104 *err = "Failed to parse JSON";
105 FL_WARN(
"Failed to parse JSON");
106 return false;
107 }
108
109 if (!jsonDoc.is_object()) {
110 *err = "JSON root is not an object";
111 FL_WARN(
"JSON root is not an object");
112 return false;
113 }
114
115
116 if (!jsonDoc.contains("map")) {
117 *err = "Missing 'map' key in JSON";
118 FL_WARN(
"Missing 'map' key in JSON");
119 return false;
120 }
121
122
123 auto mapObj = jsonDoc["map"];
124 if (!mapObj.has_value() || !mapObj.is_object()) {
125 *err = "Invalid 'map' object in JSON";
126 FL_WARN(
"Invalid 'map' object in JSON");
127 return false;
128 }
129
130 auto jsonMapOpt = mapObj.as_object();
131 if (!jsonMapOpt || jsonMapOpt->empty()) {
132 *err = "Failed to parse map from JSON or map is empty";
133 FL_WARN(
"Failed to parse map from JSON or map is empty");
134 return false;
135 }
136
137 auto& jsonMap = *jsonMapOpt;
138
139
140 for (const auto& kv : jsonMap) {
141 auto name = kv.first;
142
143
144
145 if (!kv.second) {
146 *err = "Null value for segment " + name;
147 return false;
148 }
149
150
151 fl::Json val(kv.second);
152 if (!val.has_value()) {
153 *err = "Invalid value for segment " + name;
154 return false;
155 }
156
157 if (!val.is_object()) {
158 *err = "Segment value for " + name + " is not an object";
159 return false;
160 }
161
162
163 if (!val.contains("x")) {
164 *err = "Missing x array for " + name;
165 return false;
166 }
167
168 if (!val["x"].has_value() || !val["x"].is_array()) {
169 *err = "Invalid x array for " + name;
170 return false;
171 }
172
173
175
176
177 if (!val.contains("y")) {
178 *err = "Missing y array for " + name;
179 return false;
180 }
181
182 if (!val["y"].has_value() || !val["y"].is_array()) {
183 *err = "Invalid y array for " + name;
184 return false;
185 }
186
187
189
190
191 float diameter = -1.0f;
192 if (val.contains("diameter") && val["diameter"].has_value()) {
193 auto diameterOpt = val["diameter"].as_float();
194 if (diameterOpt) {
195 diameter = static_cast<float>(*diameterOpt);
196 }
197 }
198
200 if (n != x_array.
size() || n != y_array.
size()) {
201 if (n != x_array.
size()) {
202 }
203 if (n != y_array.
size()) {
204 }
205 }
206
208 for (size_t i = 0; i < n; i++) {
209 segment_map.set(i,
vec2f{x_array[i], y_array[i]});
210 }
211 (*segmentMaps)[name] =
fl::move(segment_map);
212 }
213 return true;
214#endif
215}
static Json parse(const fl::string &txt)
constexpr remove_reference< T >::type && move(T &&t) noexcept
HeapVector< T, Allocator > vector
fl::vector< float > jsonArrayToFloatVector(const fl::Json &jsonArray)