11package dev .toonformat .jtoon .encoder ;
22
33import dev .toonformat .jtoon .EncodeOptions ;
4+ import dev .toonformat .jtoon .KeyFolding ;
5+ import dev .toonformat .jtoon .decoder .DecodeContext ;
6+ import dev .toonformat .jtoon .normalizer .JsonNormalizer ;
47import org .junit .jupiter .api .DisplayName ;
58import org .junit .jupiter .api .Test ;
9+ import tools .jackson .core .JsonGenerator ;
10+ import tools .jackson .core .JsonParser ;
11+ import tools .jackson .core .JsonToken ;
12+ import tools .jackson .databind .JsonNode ;
613import tools .jackson .databind .ObjectMapper ;
714import tools .jackson .databind .node .ArrayNode ;
815import tools .jackson .databind .node .JsonNodeFactory ;
16+ import tools .jackson .databind .node .JsonNodeType ;
917import tools .jackson .databind .node .ObjectNode ;
18+ import tools .jackson .databind .node .ValueNode ;
1019
20+ import java .io .IOException ;
1121import java .lang .reflect .Constructor ;
1222import java .lang .reflect .InvocationTargetException ;
1323import java .lang .reflect .Method ;
@@ -41,6 +51,38 @@ void givenSimpleObject_whenEncoding_thenOutputsCorrectLines() {
4151 assertEquals ("x: 10" , writer .toString ());
4252 }
4353
54+ @ Test
55+ void givenSimpleObject_withNullRootLiteralKeys_whenEncoding_thenOutputsCorrectLines () {
56+ // Given
57+ ObjectNode objectNode = MAPPER .createObjectNode ();
58+ objectNode .put ("x" , 10 );
59+
60+ EncodeOptions options = EncodeOptions .DEFAULT ;
61+ LineWriter writer = new LineWriter (options .indent ());
62+
63+ // When
64+ ObjectEncoder .encodeObject (objectNode , writer , 0 , options , null , null , null , new HashSet <>());
65+
66+ // Then
67+ assertEquals ("x: 10" , writer .toString ());
68+ }
69+
70+ @ Test
71+ void givenSimpleObject_whenEncoding_thenOutputsInCorrectLines () {
72+ // Given
73+ ObjectNode objectNode = MAPPER .createObjectNode ();
74+ objectNode .put ("x" , 10 );
75+
76+ EncodeOptions options = EncodeOptions .DEFAULT ;
77+ LineWriter writer = new LineWriter (options .indent ());
78+
79+ // When
80+ ObjectEncoder .encodeObject (objectNode , writer , 25 , options , new HashSet <>(), null , null , new HashSet <>());
81+
82+ // Then
83+ assertEquals (" x: 10" , writer .toString ());
84+ }
85+
4486 @ Test
4587 @ DisplayName ("given fully-folded primitive leaf when flatten then writes inline value and returns null" )
4688 void givenFullyFoldedPrimitiveLeaf_whenFlatten_thenWritesInlineAndReturnsNull () throws Exception {
@@ -553,10 +595,10 @@ void usesListFormatForObjectsContainingArraysOfArrays() {
553595
554596 EncodeOptions options = EncodeOptions .withFlatten (true );
555597 LineWriter writer = new LineWriter (options .indent ());
556- Set <String > rootKeys = new HashSet <>();
598+ Set <String > siblings = new HashSet <>();
557599
558600 // When
559- ObjectEncoder .encodeObject (node , writer , 0 , options , rootKeys , null , null , new HashSet <>());
601+ ObjectEncoder .encodeObject (node , writer , 0 , options , siblings , null , null , new HashSet <>());
560602
561603 // Then
562604 String expected = String .join ("\n " ,
@@ -580,10 +622,10 @@ void testEncodeKeyValuePairWithAKey() {
580622
581623 EncodeOptions options = EncodeOptions .withFlatten (true );
582624 LineWriter writer = new LineWriter (options .indent ());
583- Set <String > rootKeys = new HashSet <>();
625+ Set <String > siblings = new HashSet <>();
584626
585627 // When
586- ObjectEncoder .encodeKeyValuePair ("items" , node , writer , 0 , options , rootKeys , null , null , 10 , new HashSet <>());
628+ ObjectEncoder .encodeKeyValuePair ("items" , node , writer , 0 , options , siblings , null , null , 10 , new HashSet <>());
587629
588630 // Then
589631 String expected = String .join ("\n " ,
@@ -608,10 +650,10 @@ void testEncodeKeyValuePairWithANullKey() {
608650
609651 EncodeOptions options = EncodeOptions .withFlatten (true );
610652 LineWriter writer = new LineWriter (options .indent ());
611- Set <String > rootKeys = new HashSet <>();
653+ Set <String > siblings = new HashSet <>();
612654
613655 // When
614- ObjectEncoder .encodeKeyValuePair (null , node , writer , 0 , options , rootKeys , null , null , 10 , new HashSet <>());
656+ ObjectEncoder .encodeKeyValuePair (null , node , writer , 0 , options , siblings , null , null , 10 , new HashSet <>());
615657
616658 // Then
617659 String expected = "" ;
@@ -630,10 +672,10 @@ void testEncodeKeyValuePairWithNullFlattenDepth() {
630672
631673 EncodeOptions options = EncodeOptions .withFlatten (true );
632674 LineWriter writer = new LineWriter (options .indent ());
633- Set <String > rootKeys = new HashSet <>();
675+ Set <String > siblings = new HashSet <>();
634676
635677 // When
636- ObjectEncoder .encodeKeyValuePair ("items" , node , writer , 0 , options , rootKeys , null , null , null , new HashSet <>());
678+ ObjectEncoder .encodeKeyValuePair ("items" , node , writer , 0 , options , siblings , null , null , null , new HashSet <>());
637679
638680 // Then
639681 String expected = String .join ("\n " ,
@@ -658,10 +700,10 @@ void testEncodeKeyValuePairWithToSmallFlattenDepth() {
658700
659701 EncodeOptions options = EncodeOptions .withFlatten (true );
660702 LineWriter writer = new LineWriter (options .indent ());
661- Set <String > rootKeys = new HashSet <>();
703+ Set <String > siblings = new HashSet <>();
662704
663705 // When
664- ObjectEncoder .encodeKeyValuePair ("items" , node , writer , 0 , options , rootKeys , null , null , 0 , new HashSet <>());
706+ ObjectEncoder .encodeKeyValuePair ("items" , node , writer , 0 , options , siblings , null , null , 0 , new HashSet <>());
665707
666708 // Then
667709 String expected = String .join ("\n " ,
@@ -686,11 +728,175 @@ void testEncodeKeyValuePairWithoutEmptySiblings() {
686728 siblings .add ("world" );
687729
688730 // When
689- ObjectEncoder .encodeKeyValuePair ("" , node , writer , 0 , options , siblings , null , null , 10 , new HashSet <>());
731+ ObjectEncoder .encodeKeyValuePair ("items " , node , writer , 0 , options , siblings , null , null , null , new HashSet <>());
690732
691733 // Then
692734 assertFalse (writer .toString ().trim ().isEmpty ());
693735 //we only get a String with ""
694736 }
695737
738+ @ Test
739+ void testEncodeKeyValuePairWithKeyInBlockedKeysSet () {
740+ // Given
741+ String json = "{\n " +
742+ " \" items\" : [\n " +
743+ " { \" matrix\" : [[1, 2], [3, 4]], \" name\" : \" grid\" }\n " +
744+ " ]\n " +
745+ " }" ;
746+ ObjectNode node = (ObjectNode ) new ObjectMapper ().readTree (json );
747+
748+ EncodeOptions options = EncodeOptions .withFlatten (true );
749+ LineWriter writer = new LineWriter (options .indent ());
750+ Set <String > siblings = Set .of ("hello" , "world" );
751+ Set <String > blockedKeys = Set .of ("items" );
752+
753+ // When
754+ ObjectEncoder .encodeKeyValuePair ("items" , node , writer , 0 , options , siblings , null , null , 10 , blockedKeys );
755+
756+ // Then
757+ String expected = String .join ("\n " ,
758+ "items:" ,
759+ " items[1]:" ,
760+ " - matrix[2]:" ,
761+ " - [2]: 1,2" ,
762+ " - [2]: 3,4" ,
763+ " name: grid" );
764+ assertEquals (expected , writer .toString ());
765+ }
766+
767+ @ Test
768+ void testEncodeKeyValuePairWithoutFlattenWithAKey () {
769+ // Given
770+ String json = "{\n " +
771+ " \" items\" : [\n " +
772+ " { \" matrix\" : [[1, 2], [3, 4]], \" name\" : \" grid\" }\n " +
773+ " ]\n " +
774+ " }" ;
775+ ObjectNode node = (ObjectNode ) new ObjectMapper ().readTree (json );
776+
777+ EncodeOptions options = EncodeOptions .withFlatten (false );
778+ LineWriter writer = new LineWriter (options .indent ());
779+ Set <String > siblings = new HashSet <>();
780+
781+ // When
782+ ObjectEncoder .encodeKeyValuePair ("items" , node , writer , 0 , options , siblings , null , null , 10 , new HashSet <>());
783+
784+ // Then
785+ String expected = String .join ("\n " ,
786+ "items:" ,
787+ " items[1]:" ,
788+ " - matrix[2]:" ,
789+ " - [2]: 1,2" ,
790+ " - [2]: 3,4" ,
791+ " name: grid" );
792+ assertEquals (expected , writer .toString ());
793+ }
794+
795+ @ Test
796+ void handleFullyFoldedLeafForObjectNodeAsLeaf () throws Exception {
797+ // Given
798+ ObjectNode objectLeaf = (ObjectNode ) new ObjectMapper ().readTree ("{\" id\" :1}" );
799+ Flatten .FoldResult foldResult = new Flatten .FoldResult (
800+ "user.info" ,
801+ null ,
802+ objectLeaf ,
803+ 2
804+ );
805+
806+ EncodeOptions options = EncodeOptions .withFlatten (false );
807+ LineWriter writer = new LineWriter (options .indent ());
808+
809+ // When
810+ invokePrivateStatic ("handleFullyFoldedLeaf" , new Class []{Flatten .FoldResult .class , LineWriter .class , int .class , EncodeOptions .class , String .class }, foldResult , writer , 2 , options , "item" );
811+
812+ // Then
813+ String expected = String .join ("\n " , " item:" ,
814+ " id: 1" );
815+ assertEquals (expected , writer .toString ());
816+ }
817+
818+ @ Test
819+ void handleFullyFoldedLeafForBokenNodeAsLeaf () throws Exception {
820+ // Given
821+
822+ abstract class a extends JsonNode {
823+ protected a () {
824+ }
825+ }
826+
827+
828+ ObjectNode objectLeaf = (ObjectNode ) new ObjectMapper ().readTree ("{\" id\" :1}" );
829+ Flatten .FoldResult foldResult = new Flatten .FoldResult (
830+ "user.info" ,
831+ null ,
832+ objectLeaf ,
833+ 2
834+ );
835+
836+ EncodeOptions options = EncodeOptions .withFlatten (false );
837+ LineWriter writer = new LineWriter (options .indent ());
838+
839+ // When
840+ invokePrivateStatic ("handleFullyFoldedLeaf" , new Class []{Flatten .FoldResult .class , LineWriter .class , int .class , EncodeOptions .class , String .class }, foldResult , writer , 2 , options , "item" );
841+
842+ // Then
843+ String expected = String .join ("\n " , " item:" ,
844+ " id: 1" );
845+ assertEquals (expected , writer .toString ());
846+ }
847+
848+ @ Test
849+ void testingFlattenWithoutPathPrefix () throws Exception {
850+ // Given
851+ ObjectNode reminder = (ObjectNode ) new ObjectMapper ().readTree ("{\" id\" :2}" );
852+ ObjectNode objectLeaf = (ObjectNode ) new ObjectMapper ().readTree ("{\" id\" :1}" );
853+ Flatten .FoldResult foldResult = new Flatten .FoldResult (
854+ "user.info" ,
855+ reminder ,
856+ objectLeaf ,
857+ 2
858+ );
859+
860+ Set <String > blockedKeys = new HashSet <>();
861+
862+ EncodeOptions options = EncodeOptions .withFlatten (false );
863+ LineWriter writer = new LineWriter (options .indent ());
864+
865+ // When
866+ EncodeOptions expectedEncodeOptions = (EncodeOptions ) invokePrivateStatic ("flatten" , new Class []{String .class , Flatten .FoldResult .class , LineWriter .class , int .class , EncodeOptions .class , Set .class , String .class , Set .class , int .class }, "key" , foldResult , writer , 2 , options , Set .of (), null , blockedKeys , 3 );
867+
868+ // Then
869+ assertNull (expectedEncodeOptions );
870+ }
871+ @ Test
872+ void testingFlattenWithPathPrefix () throws Exception {
873+ // Given
874+ ObjectNode reminder = (ObjectNode ) new ObjectMapper ().readTree ("{\" id\" :2}" );
875+ ObjectNode objectLeaf = (ObjectNode ) new ObjectMapper ().readTree ("{\" id\" :1}" );
876+ Flatten .FoldResult foldResult = new Flatten .FoldResult (
877+ "user.info" ,
878+ reminder ,
879+ objectLeaf ,
880+ 2
881+ );
882+
883+ Set <String > blockedKeys = new HashSet <>();
884+
885+ EncodeOptions options = EncodeOptions .withFlatten (false );
886+ LineWriter writer = new LineWriter (options .indent ());
887+
888+ // When
889+ EncodeOptions expectedEncodeOptions = (EncodeOptions ) invokePrivateStatic ("flatten" , new Class []{String .class , Flatten .FoldResult .class , LineWriter .class , int .class , EncodeOptions .class , Set .class , String .class , Set .class , int .class }, "key" , foldResult , writer , 2 , options , Set .of (), "user" , blockedKeys , 3 );
890+
891+ // Then
892+ assertNull (expectedEncodeOptions );
893+ }
894+
895+
896+ // Reflection helpers for invoking private static methods
897+ private static Object invokePrivateStatic (String methodName , Class <?>[] paramTypes , Object ... args ) throws Exception {
898+ Method m = ObjectEncoder .class .getDeclaredMethod (methodName , paramTypes );
899+ m .setAccessible (true );
900+ return m .invoke (null , args );
901+ }
696902}
0 commit comments