package Ġcom . ke e con . rest docs . apis pec . json schema Ċ Ċ import Ġcom . fasterxml . jackson . databind . Serialization Feature Ċ import Ġcom . fasterxml . jackson . module . kotlin . jackson ObjectMapper Ċ import Ġcom . ke e con . rest docs . apis pec . json schema . Json Schema Constraints . apply Constraints Ċ import Ġcom . ke e con . rest docs . apis pec . model . Constraint Resolver . isRequired Ċ import Ġcom . ke e con . rest docs . apis pec . model . FieldDescriptor Ċ import Ġorg . ever it . json . schema . Array Schema Ċ import Ġorg . ever it . json . schema . Object Schema Ċ import Ġorg . ever it . json . schema . Schema Ċ import Ġorg . ever it . json . schema . internal . JSON Printer Ċ import Ġjava . io . String Writer Ċ import Ġjava . util . Collections . emptyList Ċ import Ġjava . util . function . Predicate Ċ Ċ class ĠJson Schema Generator Ġ{ ĊĊĠĠĠ Ġfun Ġgenerate Schema ( field Descriptors : ĠList < FieldDescriptor >, Ġtitle : ĠString ? Ġ= Ġnull ): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġjson Field Paths Ġ= Ġreduce Field Descriptors ( field Descriptors ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ ĠJson Field Path . compile ( it ) Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġschema Ġ= Ġtraverse ( emptyList (), Ġjson Field Paths , ĠObject Schema . builder (). title ( title ) Ġas ĠObject Schema . Builder ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġto Formatted String ( un Wrap Root Array ( json Field Paths , Ġschema )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReduce Ġthe Ġlist Ġof Ġfield Ġdescriptors Ġso Ġthat Ġthe Ġpath Ġof Ġeach Ġlist Ġitem Ġis Ġunique . ĊĠĠĠĠ Ġ* ĊĠĠĠĠ Ġ* ĠThe Ġimplementation Ġwill ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġreduce Field Descriptors ( field Descriptors : ĠList < FieldDescriptor >): ĠList < FieldDescriptor With Schema > Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġfield Descriptors ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ ĠField Descriptor With Schema . from FieldDescriptor ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. fold Right ( listOf ()) Ġ{ Ġfield Descriptor , Ġgroups Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgroups . first OrNull Ġ{ Ġit . equals On Path And Type ( field Descriptor ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . let Ġ{ Ġgroups Ġ} Ġ// Ġomit Ġthe Ġdescriptor Ġit Ġis Ġconsidered Ġequal Ġand Ġcan Ġbe Ġomitted ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġgroups . first OrNull Ġ{ Ġit . path Ġ== Ġfield Descriptor . path Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . let Ġ{ Ġgroups Ġ- Ġit Ġ+ Ġit . merge ( field Descriptor ) Ġ} Ġ// Ġmerge Ġthe Ġtype Ġwith Ġthe Ġdescriptor Ġwith Ġthe Ġsame Ġname ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġ( groups Ġ+ Ġfield Descriptor ) Ġ// Ġit Ġis Ġnew Ġjust Ġadd Ġit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġun Wrap Root Array ( json Field Paths : ĠList < Json Field Path >, Ġschema : ĠSchema ): ĠSchema Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( schema Ġis ĠObject Schema ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġgroups Ġ= Ġgroup Fields By First Remaining Path Segment ( emptyList (), Ġjson Field Paths ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( groups . keys . size Ġ== Ġ 1 Ġ&& Ġgroups . keys . contains (" [] ")) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIn Ġcase Ġof Ġroot Ġarray Ġwithout Ġadditional Ġfields , Ġreturn Ġthe Ġproperty Schemas Ġas Ġit Ġhas Ġalready Ġbeen Ġproperly Ġdefined Ġin Ġ[ type To Schema ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠIn Ġother Ġcases Ġwrap Ġit Ġin ĠArray Schema ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġroot Descriptor Ġ= Ġjson Field Paths . find Ġ{ Ġit . field Descriptor . path Ġ== Ġ" []" Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtake If Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġroot Descriptor ?. remaining Segments ( emptyList ()) ?. size Ġ== Ġ 1 Ġ&& Ġjson Field Paths . size Ġ== Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ?. let Ġ{ Ġschema . property Schemas [" [] "] Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: ĠArray Schema . builder (). all Item Schema ( schema . property Schemas [" [] "]) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. apply Constraints ( root Descriptor ?. field Descriptor ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. description ( root Descriptor ?. field Descriptor ?. description ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. title ( schema . title ). build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġschema ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġto Formatted String ( schema : ĠSchema ): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠobjectMapper Ġ= Ġj ack son ObjectMapper (). enable ( Serialization Feature . IND ENT _ OUTPUT ) ĊĠĠĠĠĠĠĠ Ġreturn ĠString Writer (). use Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġschema . describe To ( JSON Printer ( it )) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠobjectMapper . writeValue AsString ( object Mapper . read Tree ( it . toString ())) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġtraverse ( ĊĠĠĠĠĠĠĠ Ġtra versed Segments : ĠList < String >, ĊĠĠĠĠĠĠĠ Ġjson Field Paths : ĠList < Json Field Path >, ĊĠĠĠĠĠĠĠ Ġbuilder : ĠObject Schema . Builder ĊĠĠĠ Ġ): ĠSchema Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġgrouped Fields Ġ= Ġgroup Fields By First Remaining Path Segment ( tra versed Segments , Ġjson Field Paths ) ĊĠĠĠĠĠĠĠ Ġgrouped Fields . forEach Ġ{ Ġ( propertyName , Ġfield List ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Tra versed Segments Ġ= Ġ( tra versed Segments Ġ+ ĠpropertyName ). to Mutable List () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfield List . stream () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter ( is Direct Match ( new Tra versed Segments )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. findFirst () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġdirect Match Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( field List . size Ġ== Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġhandle EndOf Path ( builder , ĠpropertyName , Ġdirect Match . field Descriptor ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Fields Ġ= ĠArrayList ( field List ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnew Fields . remove ( direct Match ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Remaining Segments ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠpropertyName , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnew Tra versed Segments , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnew Fields , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdirect Match ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}. orElse Get Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Remaining Segments ( builder , ĠpropertyName , Ġnew Tra versed Segments , Ġfield List , Ġnull ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġbuilder . build () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġis Direct Match ( tra versed Segments : ĠList < String >): ĠPredicate < Json Field Path > Ġ{ ĊĠĠĠĠĠĠĠ Ġ// Ġwe Ġhave Ġa Ġdirect Ġmatch Ġwhen Ġthere Ġare Ġno Ġremaining Ġsegments Ġor Ġwhen Ġthe Ġonly Ġfollowing Ġelement Ġis Ġan Ġarray ĊĠĠĠĠĠĠĠ Ġreturn ĠPredicate Ġ{ Ġjson Field Path Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġremaining Segments Ġ= Ġjson Field Path . remaining Segments ( tra versed Segments ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġremaining Segments . isEmpty () Ġ|| Ġremaining Segments . size Ġ== Ġ 1 Ġ&& ĠJson Field Path . isArray Segment ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġremaining Segments [ 0 ] ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġgroup Fields By First Remaining Path Segment ( ĊĠĠĠĠĠĠĠ Ġtra versed Segments : ĠList < String >, ĊĠĠĠĠĠĠĠ Ġjson Field Paths : ĠList < Json Field Path > ĊĠĠĠ Ġ): ĠMap < String , ĠList < Json Field Path >> Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġjson Field Paths . groupBy Ġ{ Ġit . remaining Segments ( tra versed Segments )[ 0 ] Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġprocess Remaining Segments ( ĊĠĠĠĠĠĠĠ Ġbuilder : ĠObject Schema . Builder , ĊĠĠĠĠĠĠĠ ĠpropertyName : ĠString , ĊĠĠĠĠĠĠĠ Ġtra versed Segments : ĠMutable List < String >, ĊĠĠĠĠĠĠĠ Ġfields : ĠList < Json Field Path >, ĊĠĠĠĠĠĠĠ Ġproperty Field : ĠJson Field Path ? Ġ= Ġnull ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġremaining Segments Ġ= Ġfields [ 0 ]. remaining Segments ( tra versed Segments ) ĊĠĠĠĠĠĠĠ Ġif Ġ( property Field ?. field Descriptor ?. let Ġ{ Ġis Required ( it ) Ġ} Ġ== Ġtrue ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . add Required Property ( propertyName ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( remaining Segments . isNotEmpty () Ġ&& ĠJson Field Path . isArray Segment ( remaining Segments [ 0 ])) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtra versed Segments . add ( remaining Segments [ 0 ]) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . addProperty Schema ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠpropertyName , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠArray Schema . builder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. all Item Schema ( traverse ( tra versed Segments , Ġfields , ĠObject Schema . builder ())) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. apply Constraints ( property Field ?. field Descriptor ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. description ( property Field ?. field Descriptor ?. description ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . addProperty Schema ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠpropertyName , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtraverse ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtra versed Segments , Ġfields , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠObject Schema . builder () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. description ( property Field ?. field Descriptor ?. description ) Ġas ĠObject Schema . Builder ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġhandle EndOf Path ( ĊĠĠĠĠĠĠĠ Ġbuilder : ĠObject Schema . Builder , ĊĠĠĠĠĠĠĠ ĠpropertyName : ĠString , ĊĠĠĠĠĠĠĠ Ġfield Descriptor : ĠField Descriptor With Schema ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ(! field Descriptor . ignored ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( isRequired ( field Descriptor )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . add Required Property ( propertyName ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbuilder . addProperty Schema ( propertyName , Ġfield Descriptor . json Schema Type ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ