@@ -61,7 +61,9 @@ final class EncodingTests: XCTestCase {
6161 stringValue (
6262 try encoder. encode (
6363 Value ( a: 123 , b: nil ) ,
64- as: . combine(
64+ as: . combineWithKeys(
65+ Value . CodingKeys. self,
66+
6567 Encoding < Int >
6668 . withKey ( Value . CodingKeys. a)
6769 . pullback ( \. a) ,
@@ -92,7 +94,9 @@ final class EncodingTests: XCTestCase {
9294 stringValue (
9395 try encoder. encode (
9496 Value ( a: 123 , b: nil ) ,
95- as: . combine(
97+ as: . combineWithKeys(
98+ Value . CodingKeys. self,
99+
96100 Encoding < Int >
97101 . withKey ( Value . CodingKeys. a)
98102 . pullback ( \. a) ,
@@ -381,7 +385,246 @@ final class EncodingTests: XCTestCase {
381385 )
382386 }
383387
388+ // MARK: - Complex Encoding
389+
390+ func testNestedEncoding( ) {
391+ encoder. outputFormatting = . prettyPrinted
392+
393+ let car = Car (
394+ name: " McLaren F1 " ,
395+ model: . init( name: " F1 " ) ,
396+ manufacturer: . init( name: " McLaren " ) ,
397+ availableColors: [ " red " , " silver " ]
398+ )
399+
400+ XCTAssertEqual (
401+ """
402+ {
403+ " manufacturer " : {
404+ " name " : " McLaren "
405+ },
406+ " model " : {
407+ " name " : " F1 " ,
408+ " engineSizes " : [
409+ 5000,
410+ 6000,
411+ 7000
412+ ]
413+ },
414+ " availableColors " : [
415+ " RED " ,
416+ " SILVER "
417+ ],
418+ " name " : " McLaren F1 "
419+ }
420+ """ ,
421+ stringValue ( try encoder. encode ( car, as: . default) )
422+ )
423+ }
424+
425+ func testCollectionOfComplexTypes( ) {
426+ encoder. outputFormatting = . prettyPrinted
427+
428+ let carOne = Car (
429+ name: " McLaren F1 " ,
430+ model: . init( name: " F1 " ) ,
431+ manufacturer: . init( name: " McLaren " ) ,
432+ availableColors: [ " red " , " silver " ]
433+ )
434+
435+ let carTwo = Car (
436+ name: " Porsche 911 " ,
437+ model: . init( name: " 911 " ) ,
438+ manufacturer: . init( name: " Porsche " ) ,
439+ availableColors: [ " red " , " yellow " ]
440+ )
441+
442+ XCTAssertEqual (
443+ """
444+ [
445+ {
446+ " manufacturer " : {
447+ " name " : " McLaren "
448+ },
449+ " model " : {
450+ " name " : " F1 " ,
451+ " engineSizes " : [
452+ 5000,
453+ 6000,
454+ 7000
455+ ]
456+ },
457+ " availableColors " : [
458+ " RED " ,
459+ " SILVER "
460+ ],
461+ " name " : " McLaren F1 "
462+ },
463+ {
464+ " manufacturer " : {
465+ " name " : " Porsche "
466+ },
467+ " model " : {
468+ " name " : " 911 " ,
469+ " engineSizes " : [
470+ 5000,
471+ 6000,
472+ 7000
473+ ]
474+ },
475+ " availableColors " : [
476+ " RED " ,
477+ " YELLOW "
478+ ],
479+ " name " : " Porsche 911 "
480+ }
481+ ]
482+ """ ,
483+ stringValue ( try encoder. encode ( [ carOne, carTwo] , as: . arrayOf( . default) ) )
484+ )
485+ }
486+
487+ func testUnkeyedEncodingOfValueAttributes( ) {
488+ struct Value {
489+ var a : Int
490+ var b : String
491+ var c : Bool
492+ }
493+
494+ let value = Value ( a: 1 , b: " A " , c: true )
495+
496+ let encoding : Encoding < Value > = . combine(
497+ Encoding< Int> . singleValue. pullback ( \. a) ,
498+ Encoding< String> . singleValue. pullback ( \. b) ,
499+ Encoding< Bool> . singleValue. pullback ( \. c)
500+ )
501+
502+ XCTAssertEqual (
503+ """
504+ [1, " A " ,true]
505+ """ ,
506+ stringValue ( try encoder. encode ( value, as: encoding) )
507+ )
508+ }
509+
510+ func testEncodingOfValueAttributesAsArrayOfIndividualObjects( ) {
511+ struct Value {
512+ var a : Int
513+ var b : String
514+ var c : Bool
515+ }
516+
517+ enum ValueKeys : CodingKey {
518+ case a, b, c
519+ }
520+
521+ let value = Value ( a: 1 , b: " A " , c: true )
522+
523+ let encoding : Encoding < Value > = . combine(
524+ Encoding < Int > . withKey ( ValueKeys . a) . pullback ( \. a) ,
525+ Encoding < String > . withKey ( ValueKeys . b) . pullback ( \. b) ,
526+ Encoding < Bool > . withKey ( ValueKeys . c) . pullback ( \. c)
527+ )
528+
529+ XCTAssertEqual (
530+ """
531+ [{ " a " :1},{ " b " : " A " },{ " c " :true}]
532+ """ ,
533+ stringValue ( try encoder. encode ( value, as: encoding) )
534+ )
535+ }
536+
384537 private func stringValue( _ data: Data ) -> String {
385538 String ( data: data, encoding: . utf8) !
386539 }
387540}
541+
542+ // MARK: - Test encodings
543+
544+ struct Car {
545+ var name : String
546+ var model : Model
547+ var manufacturer : Manufacturer
548+ var availableColors : [ String ]
549+
550+ enum CodingKeys : CodingKey {
551+ case name
552+ case model
553+ case manufacturer
554+ case availableColors
555+ }
556+ }
557+
558+ struct Model {
559+ var name : String
560+ var engineSizes = [ 5000 , 6000 , 7000 ]
561+
562+ enum CodingKeys : CodingKey {
563+ case name
564+ case engineSizes
565+ }
566+ }
567+
568+ struct Manufacturer {
569+ var name : String
570+
571+ enum CodingKeys : CodingKey {
572+ case name
573+ }
574+ }
575+
576+ extension Encoding where Value == Manufacturer {
577+ static let name : Self = Encoding < String >
578+ . withKey ( Model . CodingKeys. name)
579+ . pullback ( \. name)
580+
581+ static let `default` : Self = . combineWithKeys(
582+ Manufacturer . CodingKeys. self,
583+ name
584+ )
585+ }
586+
587+ extension Encoding where Value == Model {
588+ static let name : Self = Encoding < String >
589+ . withKey ( Model . CodingKeys. name)
590+ . pullback ( \. name)
591+
592+ static let engineSizes : Self = Encoding < [ Int ] >
593+ . withKey ( Model . CodingKeys. engineSizes)
594+ . pullback ( \. engineSizes)
595+
596+ static let `default` : Self = . combineWithKeys(
597+ Model . CodingKeys. self,
598+ name,
599+ engineSizes
600+ )
601+ }
602+
603+ extension Encoding where Value == Car {
604+ static let name : Self = Encoding < String >
605+ . withKey ( Car . CodingKeys. name)
606+ . pullback ( \. name)
607+
608+ static let model : Self = Encoding < Model >
609+ . default
610+ . withKey ( Car . CodingKeys. model)
611+ . pullback ( \. model)
612+
613+ static let manufacturer : Self = Encoding < Manufacturer >
614+ . default
615+ . withKey ( Car . CodingKeys. manufacturer)
616+ . pullback ( \. manufacturer)
617+
618+ static let colors : Self = Encoding < [ String ] >
619+ . arrayOf ( . singleValue. pullback { $0. uppercased ( ) } )
620+ . withKey ( Car . CodingKeys. availableColors)
621+ . pullback ( \. availableColors)
622+
623+ static let `default` : Self = . combineWithKeys(
624+ Car . CodingKeys. self,
625+ name,
626+ model,
627+ manufacturer,
628+ colors
629+ )
630+ }
0 commit comments