DCodec Sample Code

  1. Generate a schema key (DKey).
    Don't have a schema yet? No problem, use no schema, or use JSON to create one at JSON2ASN.
    Schema must comply with the Dynamic Profile (check it at Analyzer).
  2. Create an instance of Oss.DCodec, load the schema (optionally).
  3. Start encoding/decoding.
DCodec (Dynamic Codec) is capable of doing three things dynamically:
  1. Dynamic loading of a schema at runtime.
  2. Dynamic encoding and decoding of data that partially match the schema and/or the bindings.
  3. Dynamic bindings, i.e. the data objects that are created at runtime and support C# dynamic type.
DCodec deals with three kids of input/output objects:
BINDINGS (C#) SCHEMA (ASN.1) MESSAGE (JSON or DER)
dynamic, DValue, POCO (predefined) schema-less, schema-based streams, strings, byte arrays

    // Hello Wold shows how to encode/decode/validate (serialize/deserialize as JSON or DER). 
    // The data in this example is a "Hello World!" string, and the schema constrains 
    // the string length to the range of 5..12 characters:
    // 
    // Schema DEFINITIONS AUTOMATIC TAGS::= BEGIN  
    //   Type ::= SEQUENCE                            
    //   {                                              
    //      hello UTF8String (SIZE (5..12))  -- length in UTF8 chars
    //   }                                              
    // END  
           // load the schema (use https://asn1.io/dynamic/DKey.aspx to get a DKey for your schema)
            var schema = new Oss.DCodec.DSchema("Zb5qQllrUFRhNcBlGA22SiGfaZEk+xA0Jw2w+UPWz11J0VGfMQd6qYG3/xAAEA55VqDUvwpnQSCcnQpy2OntMZZS5rdQLsGLN04yyQ5Sbj88DzWwzWCXkGo2F9P5LnMh4NryPkl3BLpXdbaR8mrm0ux28HLgSuRB/B5ZiOjKxyOmA9uLmGpWPwqIH98C718Y1RxnIXurnLE5H0u01qwDpelujU+5YKG5CTHu3RvqVat5j2LHWWAKRiFxFJSMX2SngF27FjdnZzceDh19xndBJfBROnzOmcHRZ/KdiWP80SJKsRDpgRIUjzAy9yXXdSsZ9jzTpz00lEaXMfsbFXs8GJ2pxw/LDGkJfpcxFwg6OcovUwM4CvkvaLygjwPlGIndtYdcr5ezbibPN1i4sPRwNWNTOgf+6rnV8UHLi3N9FEfW5xO0BJRZlliv/7f+gDLmAPEqg7d3ZJn9FEpqqjrJpXL0PVCmFR1RuaT0Sw6YqgRtQCK/k473ClXaXg4OGh8btOmGOZsaS5HHPyBV5pyIpnJIo+gymDnYIOjB9KBhdaDk6xtEw4DZoiKR2Mc7MGzdpziU0coFbUaunWN5TTxlC/Ww81kpOvHkVAguqBdI7RnKiqszuziR42W/4TXeumLd0tEYRFxrUA==");
            var type = schema.FindType("Schema.Type");

            // create and set the data object (dynamically) 
            var dataOut = new DValueObject() { ["hello"] = "Hello World" }; // valid for the above schema, i.e. UTF8String (SIZE (5..12))

            // Create a codec (either JSON or DER)
            var codec = new Oss.DCodec.JsonCodec();  // or .DerCodec() 

            // NOTE: validation is possible in two ways: 1) during Encode()/Decode() or 2) by invoking Validate() 

            // Encode/Decode with the SchemaType argument will validate the data against the provided type
            var msg = codec.Encode(dataOut, type);

            // .... send/receive JSON or DER

            codec.DecoderOptions.ValidateConstraints = true; // Constraints validation during decoding is optional 
            dynamic dataIn = codec.Decode(msg, type);

            Console.WriteLine(dataIn.Hello.ToString());

            // Validating data directly
            string json = "{'hello':'Hello World!!!!!'}"; // too long
            var conflicts = codec.Validate(json, type); // validate a string or a data binding object
            foreach (var c in conflicts)
                Console.WriteLine("Invalid data: " + c);

            /* Output:
             *  Hello World
             *  Invalid data: ConstraintViolation: Schema.Type.hello value=Hello World!!!!! (constraint: Schema.Type(SIZE(5..12)); value size: 16)
            */
    // This example shows how to decode/encode a JSON message without using a schema.
    // Schema-less scenario is suitable for early stages of app/protocol development, 
    // while data structures are still taking shape. 
    // Once the data are more or less mature a schema can be defined for them 
    // (e.g. by using this helper tool https://asn1.io/json2asn).
            var myCodec = new Oss.DCodec.JsonCodec();

            // Basic example: JSON message includes expected fields
            string json = "{ 'Name':'Falcon', 'Speed': { 'kmph':50000 }}";
            var rocket = myCodec.Decode(json);
            if (rocket["Speed"]["kmph"] > 28968 )
                    Console.WriteLine(rocket["Name"] + " will leave the orbit..");
            /* output:
                 Falcon will leave the orbit..
            */
            // More complex example: handling optional fields and special keys
            string jsonIn = "{ 'Name':'Falcon', 'Hi-Message':'Hi there', 'Speed': { 'mph':18000 }, 'Payload': [ 'car', 'GPS unit' ]} ";
            
			dynamic rocket2 = myCodec.Decode(jsonIn);
            
			// mandatory fields
            Console.WriteLine("Name: " + rocket2.Name); 
            Console.WriteLine("Message: " + rocket2["Hi-Message"]); // can't use dot notation (avoid special chars in JSON keys)
            Console.WriteLine("Speed: " + rocket2.Speed.mph.ToString()); 
            
			// optional fields
            if (rocket2.ContainsKey("Payload")) // checking the key existence for optional 
                foreach (var p in rocket2.Payload)
                    Console.WriteLine("Payload: " + p);
            Console.WriteLine("Weight: " + (rocket2.Weight ?? "absent")); // Using operator ?? for optional
            Console.WriteLine("Launch: " + rocket2.Launch?.Location); // Using operator ?. for optional

            // modify and re-encode 
            rocket2["Hi-Message"] = "Hello";
            rocket2.Speed.mph = null; // use encoder option EncodeAbsentComponents to drop/include null fields
            rocket2.Speed.kmph = 0;   // this field is new/added.
            
			myCodec.EncoderOptions.EncodeAbsentComponents = false;
            string jsonOut = myCodec.Encode(rocket2);
            
			Console.WriteLine(jsonOut);
            
			/* output:
                Name: Falcon
                Message: Hi there
                Speed: 18000
                Payload: car
                Payload: GPS unit
                Weight: absent
                Launch:
                {"Name":"Falcon","Hi-Message":"Hello","Speed":{"kmph":0},"Payload":["car","GPS unit"]}
            */
            // Let's "explore" the data (#traverse, #iterate)
			string jsonMsg = "{ 'Name':'Falcon', 'Message':'Hi there', 'Speed': { 'mph':18000 }, 'Payload': [ 'car', 'GPS unit' ] }";
            
			var dv = myCodec.Decode(jsonMsg);
            
			foreach (var field in dv.Iterator.DescendantsAndSelf)
            {
                if (field.Value.DataType == Oss.DCodec.DDataType.Array)
                    Console.WriteLine(field.Identifier + "(array):");
                else if (field.Value.DataType == Oss.DCodec.DDataType.Object)
                    Console.WriteLine(field.Identifier + "(object):");
                else
                    Console.WriteLine("  " + field.Identifier + ":" + field.Value.ToString());
                /* Output
                    (object):
                      Name:Falcon
                      Message:Hi there
                    Speed(object):
                      mph:18000
                    Payload(array):
                      0:car
                      1:GPS unit
                */
            }

        // World-Schema DEFINITIONS EXPLICIT TAGS ::= 
        // BEGIN
        //  Rocket ::= SEQUENCE
        //  {
        //      name    [10] UTF8String(SIZE(1..16)),
        //      message [11] UTF8String DEFAULT "Hello World" , 
        //      fuel    [12] ENUMERATED { solid, liquid, gas, hybrid},
        //      speed   [13] CHOICE
        //      {
        //         mph  [20] INTEGER,  
        //         kmph [21] INTEGER
        //      }  OPTIONAL, 
        //      payload [14] SEQUENCE OF UTF8String
        //   }
        // END
            // The above schema was compiled into a DKey which is loaded into DCodec at runtime. See https://asn1.io/dynamic/DKey.aspx  
            using (Stream sf = File.OpenRead("myschema.dkey"))
            {
                var mySchema = new Oss.DCodec.DSchema(sf);

                var inType = mySchema.FindType("World-Schema.Rocket");

                var inMsg = "{'Name':'Falcon', 'Fuel':'solid', 'Payload':['none']}";

                var myCodec = new Oss.DCodec.JsonCodec();

                var outData = myCodec.Decode(inMsg, inType);

                Console.WriteLine("Name=" + outData["Name"]);

				// Message is absent in JSON, so the default is taken from the schema
                if (outData.ContainsKey("Message"))
                    Console.WriteLine("Message=" + outData["Message"]);
                Console.WriteLine("Fuel=" + outData["Fuel"]);
                
				// Speed is absent in JSON, otherwise it'd be printed as ={key:value}, where key is either "mph" or "kmph"
                if (outData.ContainsKey("Speed"))
                    Console.WriteLine("Speed=" + outData["Speed"]);
                Console.WriteLine("Payload=" + outData["Payload"]);
                /* Out:
                 *  Name=Falcon
                 *  Message=Hello World
                 *  Fuel=solid
                 *  Payload=["none"]
                 */
            }
    // This example shows how to use a schema to validate messages, i.e. ensure
    // that the message contains all required fields and meets the constraints (if any).
    // Note, the example is in JSON, but DER messages will work the same way. 
    // 
    // DCodec also allows dynamic scenarios, where the schema and a message match
    // partially (see dynamic scenarios, e.g. schema evolution and partial decoding)
    // 
    // ===============================================  
    // MySchema DEFINITIONS AUTOMATIC TAGS::= BEGIN  
    //   Rocket ::= SEQUENCE                            
    //   {                                              
    //      name        UTF8String (SIZE (4..16)),                 
    //      speed       INTEGER (0..1000),                    
    //      weight      REAL (0..1000) OPTIONAL,                       
    //      units       ENUMERATED { metric, imperial }
    //   }                                              
    // END                                              
    // ===============================================  
            // Load a schema, then decode and validate messages (some valid, some not)
            var myCodec = new Oss.DCodec.JsonCodec(); 
			// load the above schema (use https://asn1.io/dynamic/DKey.aspx to convert the schema into DKey)
            var mySchema = new Oss.DCodec.DSchema(...dkey...);
            var myType = mySchema.FindType("MySchema.Rocket");

            // a valid message
            var goodMsg = "{'name':'Falcon', 'speed':0, 'units':'metric'}";
            // invalid messages
            var badMsg1 = "{'name':'Falcon'                             }"; // missing required fields
            var badMsg2 = "{'name':'xxx',    'speed':0, 'units':'metric'}"; // too short name 
            var badMsg3 = "{'name':'Falcon', 'speed':0, 'units':'knots' }"; // unknown units 

            // decode and validate
            myCodec.DecoderOptions.ValidateConstraints = true;
            var outData = myCodec.Decode(goodMsg, myType);

            try
            {
                outData = myCodec.Decode(badMsg1, myType);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                // 0808E: The DCodec operation encountered an unhandled conflict.. SchemaExtra: MySchema.Rocket.speed (missing required field from message)
            }
            try
            {
                outData = myCodec.Decode(badMsg2, myType);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                // 0808E: The DCodec operation encountered an unhandled conflict.. ConstraintViolation: MySchema.Rocket.name value=xxx (constraint: MySchema.Rocket(SIZE(4..16)); value size: 3)
            }
            try
            {
                outData = myCodec.Decode(badMsg3, myType);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                // 0808E: The DCodec operation encountered an unhandled conflict..SchemaMissing: MySchema.Rocket.units.knots value = knots(identifier not found in schema type)
            }
    // This example shows how to work with DValue - a dynamic type to hold your data.
    // Data objects are often called bindings, since they bind fields of your message with your code. 
    // Data objects can be either pre-defined at compile time (POCO) or created dynamically at runtime. 
    // There is trade-off between them, here is how they compare:
    //                    
    //                            IntelliSense       Strong typing        Access syntax
    // User-defined/POCO          full               yes                  obj.Prop
    // Dynamic/DValue/C# dynamic  none               no                   obj["Prop"] (C# dynamic obj.Prop)
                                            
            // various ways to create and init DValues 
            var minotaur = Oss.DCodec.DValue.CreateObject().Add("name", "Minotaur"); // Add(key,value) 
            var atlas = new Oss.DCodec.DValueObject();
            atlas["name"] = "Atlas"; // ["key"] = value
            var delta = new Oss.DCodec.DValueObject { ["name"] = "Delta" }; // object initializer 
            var falcon9 = new Oss.DCodec.DValueObject // object initializer 
            {
                { "name", "Falcon 9" },
                { "speed", new Oss.DCodec.DValueChoice("kmph", 50000) },
                {
                    "payload", new Oss.DCodec.DValueArray
                    {
                        "Car",
                        "GPS"
                    }
                }
            };
            dynamic taurus = new Oss.DCodec.DValueObject(); // C# dynamic wraps a DValue
            taurus.name = "Taurus"; // C# dynamic allows dot notation
            dynamic athena = Oss.DCodec.DValue.CreateObject();
            athena.name = "Athena";
            var titan = (Oss.DCodec.DValueObject) myCodec.Decode("{ 'Name':'Titan' }"); // Initializing with a JSON string 

            // Let's encode and print 
            var rockets = new List() { falcon9, atlas, minotaur, delta, taurus, titan, athena };
            foreach (var r in rockets)
                Console.WriteLine(myCodec.Encode(r));
            /* output:
                {"name":"Falcon 9","speed":{"kmph":50000},"payload":["Car","GPS"]}
                {"name":"Atlas"}
                {"name":"Minotaur"}
                {"name":"Delta"}
                {"name":"Taurus"}
                {"Name":"Titan"}
                {"name":"Athena"}
                */

                                            
            // C# dynamic type works well with JSON, when JSON keys contain no special characters (so keys are used for property names)
            dynamic rocket = myCodec.Decode("{ 'Name':'Falcon', 'Message':'Hi there', 'Speed': { 'mph':18000 }, 'Payload': [ 'car', 'GPS unit' ] }");
            Console.WriteLine("Name: " + rocket.Name);
            Console.WriteLine("Message: " + rocket["Message"]); // avoid special chars in a key
            Console.WriteLine("Speed: " + rocket.Speed.mph);
            foreach (var p in rocket.Payload)
                Console.WriteLine("Payload: " + p);
            Console.WriteLine("Weight: " + (rocket.Weight ?? "??"));
            /* output:
                Name: Falcon
                Message: Hi there
                Speed: 18000
                Payload: car
                Payload: GPS unit
                Weight: ??
            */

                                            
            // creating and encoding a DValue is as easy
            dynamic myRocket = new Oss.DCodec.DValueObject();
            myRocket.Name = "Space";
            myRocket.Message = "Hello ET";
            myRocket.Speed = new Oss.DCodec.DValueChoice("mph", 1000);
            myRocket.Payload = new Oss.DCodec.DValueArray("My car"); 
            myRocket.Payload.Add("My Radio");
            string msg = myCodec.Encode(myRocket);
            Console.WriteLine(msg);
            /* output: 
             *   {"Name":"Space","Message":"Hello ET","Speed":{"mph":1000},"Payload":["My car","My Radio"]}            
             */
                                            
            // DValue allows to explore dynamic data (e.g. to find unexpected or optional fields)
            var falcon = (Oss.DCodec.DValueObject) myCodec.Decode(@"{ 
                        'Name':'Falcon', 
                        'Message':'Hi there', 
                        'Speed': { 'mph':18000 }, 
                        'Payload': [ 'car', 'GPS unit' ], 
                        'Weight': 151.419 }");

            // enumerate children/traverse the data tree
            foreach (var elem in falcon.Iterator.Descendants)
                Console.WriteLine($"1: {elem.Indent}{elem.Identifier}:{elem.Value}");
            /* Output:
                1:   Name:Falcon
                1:   Message:Hi there
                1:   Speed:{"mph":18000}
                1:     mph:18000
                1:   Payload:["car","GPS unit"]
                1:     0:car
                1:     1:GPS unit
                1:   Weight:151.419
            */

            // enumerate generic collection 
            foreach (var field in falcon) 
                Console.WriteLine($"2:  {field.Key}:{field.Value}");
            /* Output:
                2:  Name:Falcon
                2:  Message:Hi there
                2:  Speed:{"mph":18000}
                2:  Payload:["car","GPS unit"]
                2:  Weight:151.419
            */

            // check for a field presence
            if (falcon.ContainsKey("Weight"))
                Console.WriteLine("found Weight: " + falcon["Weight"]);
            else
                Console.WriteLine("not found Weight");
            /* Output:
                found Weight: 151.419
            */            

            // find decimal fields via LINQ (note, it's bound to C# double by default)
            var numbers = from field in falcon.Iterator.Descendants
                          where field.Value.DataType == Oss.DCodec.DDataType.Double  
                          select field.Identifier;
            Console.WriteLine("Decimal fields:");
            foreach (var id in numbers)
               Console.WriteLine("  " + id);
            /* Output:
                Decimal fields:
                  Weight
            */

                                            
            // use a DValue to transform to/from POCO (e.g. to customize serialized form)
            // Let's say we have a POCO class Fruit 
			//		public class Fruit
			//		{
			//			public string Name { get; set; }
			//			public int Quantity { get; set; }
			//		}

            var apple  = new Fruit { Name = "Apple", Quantity = 100 };
            var orange = new Fruit { Name = "Orange", Quantity = 200 };
            var fruits = new List<Fruit>() { apple, orange};
            // fruits will be serialized as [{ "Name":"Apple", "Quantity":100},{ "Name":"Orange", "Quantity":200}] 
            // but we prefer a shorter form [{ "Apple":100 }, { "Orange":200}]
            // let's do it dynamically via a intermediate DValueArray 
            var fruitesTmp = new Oss.DCodec.DValueArray(fruits.Select(item => new Oss.DCodec.DValueObject() { { item.Name, item.Quantity } }));
            string jsonArray = myCodec.Encode(fruitesTmp);
            Console.WriteLine(jsonArray);
            /* Output
             *  [{"Apple":100},{"Orange":200}]
             */

                                            
            // DValueChoice - one of many, e.g. either kmph or mph
            dynamic speed = new Oss.DCodec.DValueChoice("kmph", 28968);
            Console.WriteLine(myCodec.Encode(speed));
            speed.mph = 18000; // switch to miles per hour
            Console.WriteLine(myCodec.Encode(speed));
            /* Output
             *  {"kmph":28968}
             *  {"mph":18000}
             */

                                            
    // This example shows how to work with pre-defined bindings (user defined data objects), 
    // aka POCO https://en.wikipedia.org/wiki/Plain_old_CLR_object

        // Define our data to be encoded/decoded
        public class Rocket
        {
            public string Name { get; set; }
            [Oss.DCodec.DField(CustomName = "Message")]  // DField attribute specifies a name to match JSON key
            public string Note { get; set; }
            public Speed Speed; // Binding for ASN.1 type CHOICE 
            public List<string> Payload { get; set; }
        }

        // let DCodec know that this is a special class bound to ASN.1 CHOICE. 
        // Choice of either kilometers per hour or miles per hour, but not both.
        [Oss.DCodec.DChoice]
        public class Speed 
        {
            public int? Kmph { get; set; }
            public int? Mph { get; set; }
        }
            // Encode/Decode a Rocket 
            var myCodec = new Oss.DCodec.JsonCodec();

            var NewRocket = new Rocket
            {
                Name = "Falcon Heavy",
                Note = "I'm here",
                Speed = new Speed
                {
                    Mph = 18000
                }
            };

            myCodec.EncoderOptions.Formatting = Oss.DCodec.JsonFormatting.Indented;
            string msg = myCodec.Encode(NewRocket);
            Console.WriteLine(msg);
            /* output:
                 {
                  "Name":"Falcon Heavy",
                  "Message":"I'm here",
                  "Speed":{
                    "Mph":18000
                  }
                }
            */

            // Decode a Rocket
            var jsonMsg = @"{ 
                            'Name':'Falcon', 
                            'Message':'Hi there', 
                            'Speed': { 'Mph':18000 }, 
                            'Payload': [ 'GPS unit', 'Car' ]
                         }";
            var rocket = myCodec.Decode<Rocket>(jsonMsg);

            Console.WriteLine("Name: " + rocket.Name);
            Console.WriteLine("Message: " + rocket.Note);

            if (rocket.Speed.Mph != null)
                Console.WriteLine("Speed (mph): " + rocket.Speed.Mph);
            else if (rocket.Speed.Kmph != null)
                Console.WriteLine("Speed (kmph): " + rocket.Speed.Kmph);
            else
                Console.WriteLine("Unknown speed units");

            Console.WriteLine("Payload: " + string.Join(",", rocket.Payload.ToArray()));
            /* output:
                Name: Falcon
                Message: Hi there
                Speed (mph):18000
                Payload: GPS unit,Car
            */
            // encode/decode useful/native C# types: decimal/double, List, Dictionary  
            var real64 = new List<double> { 3.14D, double.NegativeInfinity, double.PositiveInfinity, double.NaN };
            var realDec = new List<decimal> { 3.14M, decimal.MinusOne, decimal.One, decimal.Zero, decimal.MinValue, decimal.MaxValue };
            myCodec.EncoderOptions.Formatting = Oss.DCodec.JsonFormatting.None;
            Console.WriteLine(myCodec.Encode(real64));
            Console.WriteLine(myCodec.Encode(realDec));
            /* Output:
                [3.1400000000000001,"-INF","INF","NaN"]
                [3.14,-1.0,1.0,0.0,-79228162514264337593543950335.0,79228162514264337593543950335.0]
            */
            var dict = myCodec.Decode<Dictionary<string, object >>("{'Name':'Falcon', 'Message':'Hi there', 'Speed': { 'mph':18000 }, 'Payload': [ 'car', 'GPS unit' ] }");
            Console.WriteLine(myCodec.Encode(dict));
            /* Output:
             *   {"Name":"Falcon","Message":"Hi there","Speed":{"mph":18000},"Payload":["car","GPS unit"]}
             */
            // convert DValue to/from POCO
            var dvRocket = new Oss.DCodec.DValueObject { ["name"] = "Delta", ["Payload"] = new Oss.DCodec.DValueArray { "Car", "GPS" } };

            var pocoRocket = dvRocket.ToObject<Rocket>();
            dvRocket = Oss.DCodec.DValue.FromObject(pocoRocket) as Oss.DCodec.DValueObject;

    // Usually the schema, the message, and the bindings match each other. E.g. a Rocket has 
    // a Speed property which is a number, then Speed must appear in the user defined bindings, 
    // in the schema, and in the message, or otherwise something is wrong. 
    // However the data change/evolve all the time, sometime unexpected, which cause 
    // "conflicts" during serialization/validation. There are different kinds of Conflicts, 
    // and mostly during Decode, since the incoming data are more likely to deviate. 
    // With DCodec the app can handle conflicts and recover from them (e.g. to be 
    // "liberal on receiving") without interrupting the operation. The app just have to provide 
    // a conflict handler, because otherwise DCodec throws an exception.
    //
    // Lets define three sets of data for a Rocket: the schema type, the binding class, and a JSON message
    // each slightly different from the other two and see which conflicts the app receives 
    // during serialization and validation.

        // Schema
        // World-Schema-C DEFINITIONS EXPLICIT TAGS::= BEGIN         
        //   Rocket ::= SEQUENCE                                     
        //   {                                                     
        //      name        [1] UTF8String,                       
        //      speed       [2] INTEGER (1..100000),                       
        //      weight      [3] REAL,                       
        //      units       [7] ENUMERATED { metric, royal },
        // 	    payload     [8] SEQUENCE SIZE(10) OF UTF8String OPTIONAL,      
        // 	    oneway      [9] BOOLEAN OPTIONAL      
        //   }
        // END

        // Pre-defined bindings (POCO)
        public class Rocket4
        {
            public string Name { get; set; }
            public string Date { get; set; }
            public int Speed { get; set; }
            public int Stages { get; set; }
            public U Units {get; set;}
            public enum U { metric, royal }
            public bool? Oneway { get; set; } // OPTIONAL
        }

        public Oss.DCodec.DResponse ConflictsHandlerPrintAndContinue(Oss.DCodec.DConflict conflict)
        {
            System.Console.WriteLine(conflict);
            return Oss.DCodec.DResponse.Continue;
        }
            var myCodec = new Oss.DCodec.JsonCodec();
            // we'll use default conflicts/validation options
            // myCodec.DecoderOptions.ValidateConstraints = true; // to validate constraints during decoding
            // myCodec.DecoderOptions.ConflictsValue = Oss.DCodec.DConflictsValue.Parse;
            // Schema-less decoding fires a few conflicts. For each field let's see if there is a conflict: 
            //  Bindings            Message
            //  string Name        'Name':'My rocket' -- no conflict, name and type match
            //  string Date        'Date':2018        -- no conflict, number is converted to string
            //  int Speed          'Speed':null       -- no conflict, null is converted to 0
            //  int Stages         'Stages':'ABC'     -- BindingTypeMismatch, string cannot be converted into int
            //    --               'Weight':250000    -- BindingMissing, binding is missing this field
            //  enum Units           --               -- no conflict, extra fields in the bindings are not a problem
            //                     'Name':'Rocket'    -- DuplicatedKey, Name was encountered twice
            //    --                  --              -- no conflict, Payload is only in the schema, but we don't use schema yet
            //  bool? Oneway        'Oneway':null     -- no conflict, binding is nullable, hence optional

            string msg=@"{
                            'Name' : 'My rocket' ,
                            'Date' : 2018,
                            'Speed' : null,
                            'Stages' : 'ABC' ,
                            'Weight' : 250000,
                            'Name' : 'Rocket' ,
                            'Oneway' : null
                        }";
            var rocket=myCodec.DecodeDynamic<Rocket4>(msg, ConflictsHandlerPrintAndContinue); // a liberal handler: c => {Log(); return DResponse.Continue;}
            /* Output
                BindingTypeMismatch: Stages value=ABC
                BindingMissing: Weight value=250000
                DuplicatedKey: Name value=Rocket
            */

            // Schema-less encode fire no conflicts, since the message just follows the bindings.
            var encoding = myCodec.Encode(rocket);
            /* No Output, there is no conflicts
            */
            // Using a schema bring more potential conflicts than schema-less decoding (schema key generated @ http://asn1.io/dynamic)
            var mySchema = new Oss.DCodec.DSchema("...");

            //  Bindings      Schema           Message
            //  string Name   name   UTF8     'Name'  : 'Fake rocket' -- no conflicts
            //  string Date     --            'Date'  : 2018,         -- SchemaMissing (schema has no Date) but no type mismatch (number is converted)
            //  int Speed     speed  INT      'Speed' : null,         -- SchemaTypeMismatch, BindingTypeMismatch, null cannot be used for a required field
            //  int Stages     --             'Stages': 'ABC',        -- BindingTypeMismatch, SchemaMissing
            //    --          weight REAL     'Weight': true,         -- BindingMissing, SchemaTypeMismatch (REAL vs boolean).
            //  enum Units    units  ENUM       --                    -- SchemaExtra, units is expected in the message
            //                                'Name'  : 'Test rocket' -- DuplicatedKey
            //    --         payload INT OPT      --                  -- no conflicts, Payload is OPTIONAL
            //  bool Oneway   oneway BOOL     'Oneway':null           -- no conflicts, OPTIONAL, null in the message, no conflicts

            // Message
            msg = @"{ 
                        'Name'  : 'Fake rocket',
                        'Date'  : 2018,
                        'Speed' : null,
                        'Stages': 'ABC', 
                        'Weight': true,
                        'Name'  : 'Test rocket',
                        'Oneway': null
                    }";
            
            rocket = myCodec.DecodeDynamic<Rocket4>(msg, mySchema.FindType("World-Schema-C.Rocket"), ConflictsHandlerPrintAndContinue);
            /* Output
                SchemaMissing: World-Schema-C.Rocket.Date value=2018 
                SchemaTypeMismatch: World-Schema-C.Rocket.speed 
                BindingTypeMismatch: World-Schema-C.Rocket.speed 
                BindingTypeMismatch: World-Schema-C.Rocket.Stages value=ABC 
                SchemaMissing: World-Schema-C.Rocket.Stages value=0 
                SchemaTypeMismatch: World-Schema-C.Rocket.weight value=True 
                BindingMissing: World-Schema-C.Rocket.weight value=True 
                DuplicatedKey: World-Schema-C.Rocket.name value=Test rocket
                SchemaExtra: World-Schema-C.Rocket.units 
            */

            Console.WriteLine("-------------------- Conflicts of decoding dynamic type --------------------");
            // for a dynamic type, the output object is created dynamically, so there is no binding conflicts
            var dvRocket = myCodec.DecodeDynamic(msg, mySchema.FindType("World-Schema-C.Rocket"), ConflictsHandlerPrintAndContinue);
            /*
               SchemaMissing: World-Schema.Rocket.Date value=2018
               SchemaTypeMismatch: World-Schema.Rocket.speed 
               SchemaMissing: World-Schema.Rocket.Stages value=ABC
               SchemaTypeMismatch: World-Schema.Rocket.weight value=True
               DuplicatedKey: World-Schema.Rocket.name value=Test rocket
               SchemaExtra: World-Schema.Rocket.units
            */

            // mismatched ENUM or CHOICE items also result in conflicts 
            msg = @"{ 'Name':'Alpha','Speed' : 1, 'Units':'British'}";  // "British" is not in the schema 
            dvRocket = myCodec.DecodeDynamic(msg, mySchema.FindType("World-Schema-C.Rocket"), ConflictsHandlerPrintAndContinue);
            /*
                SchemaMissing: World-Schema-C.Rocket.units.British value=British
                SchemaExtra: World-Schema-C.Rocket.weight            
            */

            dvRocket["Units"] = "British"; //  "British" is not in the schema
            msg = myCodec.EncodeDynamic(dvRocket, mySchema.FindType("World-Schema-C.Rocket"), ConflictsHandlerPrintAndContinue);
            /*
                SchemaExtra: World-Schema-C.Rocket.weight 
                SchemaMissing: World-Schema-C.Rocket.units.British value=British 
            */
            // Validating and enumerating the conflicts
            dvRocket = new Oss.DCodec.DValueObject
            {
                { "Name", "Delta" },
                { "Speed", -1 },        // invalid, must be 1..100000
                { "Units", "metric" }   
                // { "Weight", 100.0 }  // invalid, is required
            };
            var problems = myCodec.Validate(dvRocket, mySchema.FindType("World-Schema-C.Rocket"));
            foreach (var p in problems)
                Console.WriteLine(p);
            /* output:
                ConstraintViolation: World-Schema-C.Rocket.speed value=-1 
                SchemaExtra: World-Schema-C.Rocket.weight
             */
    // This example shows how to do а partial decoding, e.g. when the application  
    // needs only a few fields (out of a big message) and the rest can be ignored. 
    // Let's consider this schema as "big", with "lots" of fields, while the app 
    // needs only Rocket.Speed to perform its logic. Also note, that the schema
    // can be extended later by adding fields in Rocket.Other.
    // ===============================================         
    // World-Schema DEFINITIONS EXPLICIT TAGS::= BEGIN         
    //   Rocket ::= SEQUENCE                                     
    //   {                                                     
    //      name        [1] UTF8String,                       
    //      speed       [2] INTEGER,                       
    //      other       [3] SEQUENCE { ... } -- extensible
    //   }                                                     
    // END                                                     
    // ===============================================                                                                

    // Data type to decode into (bindings)
    public class Essentials
    {
        // not interested in 
        //   public string Name { get; set; }
        //   public Stuff other { get; set; }
        public int Speed { get; set; }
    }
            // Partial decoding - when only parts of the message are decoded
            var myCodec = new JsonCodec();

            // Load the schema (dkey is generated with http://asn1.io/dynamic)
            var mySchema = new DSchema("....dkey....");

            // message includes lots of stuff, but only Speed is essential for this app
            string msg = "{ 'Name':'Gemini', 'Speed':45000,  'Other':{'id':'x1234', 'size':20, 'Payload':true, 'Launches':[1964,1965,1966]} }";

            // bindings and the message partially match the schema, so conflicts are expected (and handled).
            var rocket = myCodec.DecodeDynamic<Essentials>(msg,  mySchema.FindType("World-Schema.Rocket"),  MyHandler);

            if (rocket.Speed > 40000)
                Console.WriteLine("Orbiting...");
            // Output:
            //    New field:   World-Schema.Rocket.other.id
            //    New field:   World-Schema.Rocket.other.size
            //    New field:   World-Schema.Rocket.other.Payload
            //    New field:   World-Schema.Rocket.other.Launches
            //    Orbiting...
        public DResponse MyHandler(DConflict conflict)
        {
            switch (conflict.Kind)
            {
                // Ignore fields that are not essential
                case DConflictKind.BindingMissing:
                    return DResponse.Drop;

                // Log fields that are new (do not match the schema)
                case DConflictKind.SchemaMissing:
                    System.Console.WriteLine("New field:   " + conflict.Reference); 
                    return DResponse.Continue;

                // Break on any other kind of conflict. DOperationInterupted will be thrown.
                default:
                    return DResponse.Break; 
            }
        }

    // This example shows 
            var myCodec = new Oss.DCodec.JsonCodec(); 
    // This example shows 
            var myCodec = new Oss.DCodec.JsonCodec();