@@ -17,7 +17,7 @@ use super::*;
17
17
use snarkos_node_router:: { SYNC_LENIENCY , messages:: UnconfirmedSolution } ;
18
18
use snarkvm:: {
19
19
ledger:: puzzle:: Solution ,
20
- prelude:: { Address , Identifier , LimitedWriter , Plaintext , ToBytes , block:: Transaction } ,
20
+ prelude:: { Address , Identifier , LimitedWriter , Plaintext , ToBytes , Value , block:: Transaction } ,
21
21
} ;
22
22
23
23
use indexmap:: IndexMap ;
@@ -220,13 +220,47 @@ impl<N: Network, C: ConsensusStorage<N>, R: Routing<N>> Rest<N, C, R> {
220
220
// Check if metadata is requested and return the value with metadata if so.
221
221
if metadata. metadata . unwrap_or ( false ) {
222
222
return Ok ( ErasedJson :: pretty ( json ! ( {
223
- "data" : mapping_value,
223
+ "data" : Self :: value_to_json ( mapping_value) ,
224
224
"height" : rest. ledger. latest_height( ) ,
225
225
} ) ) ) ;
226
226
}
227
227
228
- // Return the value without metadata.
229
- Ok ( ErasedJson :: pretty ( mapping_value) )
228
+ Ok ( ErasedJson :: pretty ( Self :: value_to_json ( mapping_value) ) )
229
+ }
230
+
231
+ /// Convert a `Value` to JSON.
232
+ /// `Value` implements Serialize by just calling `to_string()` on the value, which leads to Display
233
+ /// output which (sometimes) looks like JSON but isn't.
234
+ /// We produce actual JSON by calling `serde_json::to_value` on the inner object.
235
+ fn value_to_json ( mapping_value : Option < Value < N > > ) -> serde_json:: Value {
236
+ if let Some ( mapping_value) = mapping_value {
237
+ match mapping_value {
238
+ Value :: Plaintext ( plaintext) => match plaintext {
239
+ Plaintext :: Array ( array, _) => serde_json:: to_value ( & array) . unwrap ( ) ,
240
+ Plaintext :: Struct ( map, _) => serde_json:: to_value ( & map) . unwrap ( ) ,
241
+ Plaintext :: Literal ( literal, _) => serde_json:: to_value ( & literal) . unwrap ( ) ,
242
+ } ,
243
+ Value :: Record ( record) => serde_json:: to_value ( & record) . unwrap ( ) ,
244
+ Value :: Future ( future) => serde_json:: to_value ( & future) . unwrap ( ) ,
245
+ }
246
+ } else {
247
+ json ! ( "{}" )
248
+ }
249
+ }
250
+
251
+ fn vec_to_json ( mapping_values : & Vec < ( Plaintext < N > , Value < N > ) > ) -> serde_json:: Value {
252
+ let mut json = serde_json:: Map :: new ( ) ;
253
+ for ( ref key, ref value) in mapping_values {
254
+ let key = match key {
255
+ // TODO: not sure if keys can be anything other than literals
256
+ Plaintext :: Array ( array, _) => serde_json:: to_string ( array) . unwrap ( ) ,
257
+ Plaintext :: Struct ( map, _) => serde_json:: to_string ( map) . unwrap ( ) ,
258
+ // We can not use json here as it would cause the key to be escaped
259
+ Plaintext :: Literal ( literal, _) => literal. to_string ( ) ,
260
+ } ;
261
+ json. insert ( key, Self :: value_to_json ( Some ( value. clone ( ) ) ) ) ;
262
+ }
263
+ serde_json:: Value :: Object ( json)
230
264
}
231
265
232
266
// GET /<network>/program/{programID}/mapping/{mappingName}?all={true}&metadata={true}
@@ -251,13 +285,13 @@ impl<N: Network, C: ConsensusStorage<N>, R: Routing<N>> Rest<N, C, R> {
251
285
// Check if metadata is requested and return the mapping with metadata if so.
252
286
if metadata. metadata . unwrap_or ( false ) {
253
287
return Ok ( ErasedJson :: pretty ( json ! ( {
254
- "data" : mapping_values,
288
+ "data" : Self :: vec_to_json ( & mapping_values) ,
255
289
"height" : height,
256
290
} ) ) ) ;
257
291
}
258
292
259
293
// Return the full mapping without metadata.
260
- Ok ( ErasedJson :: pretty ( mapping_values) )
294
+ Ok ( ErasedJson :: pretty ( Self :: vec_to_json ( & mapping_values) ) )
261
295
}
262
296
Ok ( Err ( err) ) => Err ( RestError ( format ! ( "Unable to read mapping - {err}" ) ) ) ,
263
297
Err ( err) => Err ( RestError ( format ! ( "Unable to read mapping - {err}" ) ) ) ,
0 commit comments