@@ -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 ;
@@ -212,13 +212,47 @@ impl<N: Network, C: ConsensusStorage<N>, R: Routing<N>> Rest<N, C, R> {
212
212
// Check if metadata is requested and return the value with metadata if so.
213
213
if metadata. metadata . unwrap_or ( false ) {
214
214
return Ok ( ErasedJson :: pretty ( json ! ( {
215
- "data" : mapping_value,
215
+ "data" : Self :: value_to_json ( mapping_value) ,
216
216
"height" : rest. ledger. latest_height( ) ,
217
217
} ) ) ) ;
218
218
}
219
219
220
- // Return the value without metadata.
221
- Ok ( ErasedJson :: pretty ( mapping_value) )
220
+ Ok ( ErasedJson :: pretty ( Self :: value_to_json ( mapping_value) ) )
221
+ }
222
+
223
+ /// Convert a `Value` to JSON.
224
+ /// `Value` implements Serialize by just calling `to_string()` on the value, which leads to Display
225
+ /// output which (sometimes) looks like JSON but isn't.
226
+ /// We produce actual JSON by calling `serde_json::to_value` on the inner object.
227
+ fn value_to_json ( mapping_value : Option < Value < N > > ) -> serde_json:: Value {
228
+ if let Some ( mapping_value) = mapping_value {
229
+ match mapping_value {
230
+ Value :: Plaintext ( plaintext) => match plaintext {
231
+ Plaintext :: Array ( array, _) => serde_json:: to_value ( & array) . unwrap ( ) ,
232
+ Plaintext :: Struct ( map, _) => serde_json:: to_value ( & map) . unwrap ( ) ,
233
+ Plaintext :: Literal ( literal, _) => serde_json:: to_value ( & literal) . unwrap ( ) ,
234
+ } ,
235
+ Value :: Record ( record) => serde_json:: to_value ( & record) . unwrap ( ) ,
236
+ Value :: Future ( future) => serde_json:: to_value ( & future) . unwrap ( ) ,
237
+ }
238
+ } else {
239
+ json ! ( "{}" )
240
+ }
241
+ }
242
+
243
+ fn vec_to_json ( mapping_values : & Vec < ( Plaintext < N > , Value < N > ) > ) -> serde_json:: Value {
244
+ let mut json = serde_json:: Map :: new ( ) ;
245
+ for ( ref key, ref value) in mapping_values {
246
+ let key = match key {
247
+ // TODO: not sure if keys can be anything other than literals
248
+ Plaintext :: Array ( array, _) => serde_json:: to_string ( array) . unwrap ( ) ,
249
+ Plaintext :: Struct ( map, _) => serde_json:: to_string ( map) . unwrap ( ) ,
250
+ // We can not use json here as it would cause the key to be escaped
251
+ Plaintext :: Literal ( literal, _) => literal. to_string ( ) ,
252
+ } ;
253
+ json. insert ( key, Self :: value_to_json ( Some ( value. clone ( ) ) ) ) ;
254
+ }
255
+ serde_json:: Value :: Object ( json)
222
256
}
223
257
224
258
// GET /<network>/program/{programID}/mapping/{mappingName}?all={true}&metadata={true}
@@ -243,13 +277,13 @@ impl<N: Network, C: ConsensusStorage<N>, R: Routing<N>> Rest<N, C, R> {
243
277
// Check if metadata is requested and return the mapping with metadata if so.
244
278
if metadata. metadata . unwrap_or ( false ) {
245
279
return Ok ( ErasedJson :: pretty ( json ! ( {
246
- "data" : mapping_values,
280
+ "data" : Self :: vec_to_json ( & mapping_values) ,
247
281
"height" : height,
248
282
} ) ) ) ;
249
283
}
250
284
251
285
// Return the full mapping without metadata.
252
- Ok ( ErasedJson :: pretty ( mapping_values) )
286
+ Ok ( ErasedJson :: pretty ( Self :: vec_to_json ( & mapping_values) ) )
253
287
}
254
288
Ok ( Err ( err) ) => Err ( RestError ( format ! ( "Unable to read mapping - {err}" ) ) ) ,
255
289
Err ( err) => Err ( RestError ( format ! ( "Unable to read mapping - {err}" ) ) ) ,
0 commit comments