@@ -397,7 +397,7 @@ impl MorpheusHttpClient {
397397 . send ( )
398398 . await
399399 . map_err ( ClientError :: http) ?;
400- parse_json ( res) . await
400+ parse_query_result_json ( res) . await
401401 }
402402
403403 pub async fn query_explain (
@@ -554,6 +554,100 @@ async fn parse_json<T: serde::de::DeserializeOwned>(
554554 } ) )
555555}
556556
557+ async fn parse_query_result_json (
558+ res : reqwest:: Response ,
559+ ) -> Result < ApiResponse < QueryResult > , ClientError > {
560+ let status = res. status ( ) ;
561+ if status. is_success ( ) {
562+ let body = res
563+ . json :: < serde_json:: Value > ( )
564+ . await
565+ . map_err ( ClientError :: http) ?;
566+ return normalize_query_result_response ( body) ;
567+ }
568+
569+ let body = match res. json :: < ApiErrorBody > ( ) . await {
570+ Ok ( body) => body,
571+ Err ( _) => ApiErrorBody {
572+ code : "http_error" . to_string ( ) ,
573+ message : format ! ( "HTTP {status}" ) ,
574+ } ,
575+ } ;
576+ Err ( ClientError :: api ( ApiError {
577+ status : status. as_u16 ( ) ,
578+ body,
579+ } ) )
580+ }
581+
582+ fn normalize_query_result_response (
583+ body : serde_json:: Value ,
584+ ) -> Result < ApiResponse < QueryResult > , ClientError > {
585+ if let Ok ( parsed) = serde_json:: from_value :: < ApiResponse < QueryResult > > ( body. clone ( ) ) {
586+ return Ok ( parsed) ;
587+ }
588+
589+ #[ derive( serde:: Deserialize ) ]
590+ struct LegacyQueryResponse {
591+ data : Vec < CellDto > ,
592+ }
593+
594+ if let Ok ( parsed) = serde_json:: from_value :: < LegacyQueryResponse > ( body) {
595+ return Ok ( ApiResponse {
596+ data : QueryResult {
597+ cells : parsed. data ,
598+ hit_table : Default :: default ( ) ,
599+ } ,
600+ } ) ;
601+ }
602+
603+ Err ( ClientError :: invalid_argument (
604+ "query response body did not match expected formats" ,
605+ ) )
606+ }
607+
608+ #[ cfg( test) ]
609+ mod tests {
610+ use super :: * ;
611+ use serde_json:: json;
612+
613+ #[ test]
614+ fn normalize_query_result_response_accepts_structured_shape ( ) {
615+ let parsed = normalize_query_result_response ( json ! ( {
616+ "data" : {
617+ "cells" : [ {
618+ "id" : "JEFLHiLiF34zS6AVQMKYQy" ,
619+ "header" : { } ,
620+ "data" : { "content" : "x" }
621+ } ] ,
622+ "hit_table" : {
623+ "JEFLHiLiF34zS6AVQMKYQy" : {
624+ "1:bm25" : 0.5
625+ }
626+ }
627+ }
628+ } ) )
629+ . expect ( "structured response should parse" ) ;
630+
631+ assert_eq ! ( parsed. data. cells. len( ) , 1 ) ;
632+ assert_eq ! ( parsed. data. hit_table. len( ) , 1 ) ;
633+ }
634+
635+ #[ test]
636+ fn normalize_query_result_response_accepts_legacy_array_shape ( ) {
637+ let parsed = normalize_query_result_response ( json ! ( {
638+ "data" : [ {
639+ "id" : "JEFLHiLiF34zS6AVQMKYQy" ,
640+ "header" : { } ,
641+ "data" : { "content" : "x" }
642+ } ]
643+ } ) )
644+ . expect ( "legacy response should parse" ) ;
645+
646+ assert_eq ! ( parsed. data. cells. len( ) , 1 ) ;
647+ assert ! ( parsed. data. hit_table. is_empty( ) ) ;
648+ }
649+ }
650+
557651pub fn validate_base58_id ( s : & str ) -> Result < ( ) , ClientError > {
558652 let bytes = bs58:: decode ( s)
559653 . into_vec ( )
0 commit comments