diff --git a/source/siryul/common.d b/source/siryul/common.d index 58cb18b..c7a1060 100644 --- a/source/siryul/common.d +++ b/source/siryul/common.d @@ -82,6 +82,8 @@ struct CustomParser { enum AsString; ///Write field as binary (NYI) enum AsBinary; +///Errors are ignored; value will be .init +enum IgnoreErrors; alias isSimpleList = templateAnd!(isIterable, templateNot!isSomeString); static assert(isSimpleList!(int[])); diff --git a/source/siryul/dyaml.d b/source/siryul/dyaml.d index 0bae239..6713a9b 100644 --- a/source/siryul/dyaml.d +++ b/source/siryul/dyaml.d @@ -98,7 +98,12 @@ private T fromYAML(T, BitFlags!DeSiryulize flags)(Node node) @safe if (!isInfini } else enforce(node.containsKey(memberName), new YAMLException("Missing non-@Optional "~memberName~" in node")); alias fromFunc = getConvertFromFunc!(T, __traits(getMember, output, member)); - __traits(getMember, output, member) = fromFunc(node[memberName].fromYAML!(Parameters!(fromFunc)[0], flags)); + static if (hasUDA!(__traits(getMember, T, member), IgnoreErrors)) { + try { + __traits(getMember, output, member) = fromFunc(node[memberName].fromYAML!(Parameters!(fromFunc)[0], flags)); + } catch (YAMLException) {} + } else + __traits(getMember, output, member) = fromFunc(node[memberName].fromYAML!(Parameters!(fromFunc)[0], flags)); } return output; } else static if(isOutputRange!(T, ElementType!T)) { @@ -127,6 +132,7 @@ private T fromYAML(T, BitFlags!DeSiryulize flags)(Node node) @safe if (!isInfini output[fromYAML!(KeyType!T, flags)(key)] = fromYAML!(ValueType!T, flags)(value); return output; } else static if (is(T == bool)) { + enforce(node.tag == `tag:yaml.org,2002:bool`, new YAMLException("Expecting a boolean value")); return node.get!T; } else static assert(false, "Cannot read type "~T.stringof~" from YAML"); //unreachable, hopefully. diff --git a/source/siryul/json.d b/source/siryul/json.d index e8a7811..15a3905 100644 --- a/source/siryul/json.d +++ b/source/siryul/json.d @@ -60,6 +60,7 @@ private T fromJSON(T, BitFlags!DeSiryulize flags)(JSONValue node) @trusted if (! return node.integer.to!T; if (node.type == JSON_TYPE.NULL) return T.init; + expect(node, JSON_TYPE.STRING); return node.str.to!T; } else static if (isSomeChar!T) { expect(node, JSON_TYPE.STRING, JSON_TYPE.NULL); @@ -80,7 +81,13 @@ private T fromJSON(T, BitFlags!DeSiryulize flags)(JSONValue node) @trusted if (! } else enforce(memberName in node.object, new JSONDException("Missing non-@Optional "~memberName~" in node")); alias fromFunc = getConvertFromFunc!(T, field); - __traits(getMember, output, member) = fromFunc(node[memberName].fromJSON!(Parameters!(fromFunc)[0], flags)); + static if (hasUDA!(field, IgnoreErrors)) { + try { + __traits(getMember, output, member) = fromFunc(node[memberName].fromJSON!(Parameters!(fromFunc)[0], flags)); + } catch (UnexpectedTypeException) {} //just skip it + } else { + __traits(getMember, output, member) = fromFunc(node[memberName].fromJSON!(Parameters!(fromFunc)[0], flags)); + } } return output; } else static if(isOutputRange!(T, ElementType!T)) { diff --git a/source/siryul/siryul.d b/source/siryul/siryul.d index 9f2e2b0..fa72abf 100644 --- a/source/siryul/siryul.d +++ b/source/siryul/siryul.d @@ -435,6 +435,19 @@ version(unittest) { runTest2Fail!(float[])(3); //Precision loss should be rejected by default runTest2Fail!int(3.5); + //bool -> string??? + runTest2Fail!string(true); + //string -> bool??? + runTest2Fail!bool("nah"); + + struct IgnoreErrBad { + float n = 1.2; + } + struct IgnoreErrGood { + @IgnoreErrors int n = 5; + } + foreach (siryulizer; siryulizers) + assert(IgnoreErrBad().toString!siryulizer.fromString!(IgnoreErrGood, siryulizer).n == IgnoreErrGood.init.n, "IgnoreErrors test failed for "~siryulizer.stringof); } ///Use standard ISO8601 format for dates and times - YYYYMMDDTHHMMSS.FFFFFFFTZ enum ISO8601;