1 /** 2 License: 3 Boost Software License - Version 1.0 - August 17th, 2003 4 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 27 Authors: 28 aermicioi 29 **/ 30 module aermicioi.aedi_property_reader.json.json_factory; 31 32 import aermicioi.aedi_property_reader.convertor_factory; 33 import aermicioi.aedi.factory; 34 import aermicioi.aedi.storage.locator; 35 import aermicioi.aedi.storage.wrapper; 36 import aermicioi.aedi.storage.decorator; 37 import aermicioi.aedi.exception; 38 import std.json; 39 import std.traits; 40 41 /** 42 A convertor factory that uses custom fromJson family of functions to convert JSONValue into To types. 43 44 Params: 45 FromType = original representation form of data to be converted. 46 ToType = type of component that is built based on FromType data. 47 **/ 48 class JsonConvertorFactory(To, From : JSONValue = JSONValue) : ConvertorFactory!(JSONValue, To) { 49 50 private { 51 52 Locator!() locator_; 53 JSONValue convertible_; 54 } 55 56 public { 57 58 @property { 59 /** 60 Set convertible 61 62 Params: 63 convertible = data that the factory should convert into To component 64 Returns: 65 JsonConvertorFactory!(To, From) 66 **/ 67 JsonConvertorFactory!(To, From) convertible(JSONValue convertible) @safe nothrow { 68 this.convertible_ = convertible; 69 70 return this; 71 } 72 73 /** 74 Get convertible data 75 76 Returns: 77 JSONValue 78 **/ 79 JSONValue convertible() @safe nothrow { 80 return this.convertible_; 81 } 82 83 /** 84 Get the type info of T that is created. 85 86 Returns: 87 TypeInfo object of created component. 88 **/ 89 TypeInfo type() { 90 return typeid(To); 91 } 92 93 /** 94 Set a locator to object. 95 96 Params: 97 locator = the locator that is set to oject. 98 99 Returns: 100 LocatorAware. 101 **/ 102 JsonConvertorFactory!(To, From) locator(Locator!() locator) @safe nothrow { 103 this.locator_ = locator; 104 105 return this; 106 } 107 } 108 109 /** 110 Instantiates component of type To. 111 112 Returns: 113 To instantiated component. 114 **/ 115 To factory() { 116 return fromJson!To(this.convertible()); 117 } 118 } 119 } 120 121 package { 122 import std.conv : to; 123 124 /** 125 Convert JSONValue into T scalar/array/assocarray value. 126 127 Params: 128 value = storage where to put converted JSONValue 129 json = the data that is to be converted. 130 Throws: 131 InvalidCastException when the type of value does not match stored data. 132 Returns: 133 value 134 **/ 135 auto ref fromJson(T)(auto ref T value, auto ref JSONValue json) 136 if (isFloatingPoint!T) { 137 138 if (json.type != JSON_TYPE.FLOAT) { 139 throw new InvalidCastException("Could not convert json " ~ json.toString() ~ " value to type " ~ fullyQualifiedName!T); 140 } 141 142 value = json.floating.to!T; 143 144 return value; 145 } 146 147 /** 148 ditto 149 **/ 150 auto ref fromJson(T)(auto ref T value, auto ref JSONValue json) 151 if (isUnsigned!T && isIntegral!T) { 152 153 if ((json.type == JSON_TYPE.INTEGER) && (json.integer >= 0)) { 154 value = json.integer.to!T; 155 return value; 156 } 157 158 if (json.type != JSON_TYPE.UINTEGER) { 159 throw new InvalidCastException("Could not convert json " ~ json.toString() ~ " value to type " ~ fullyQualifiedName!T); 160 } 161 162 value = json.uinteger.to!T; 163 164 return value; 165 } 166 167 /** 168 ditto 169 **/ 170 auto ref fromJson(T)(auto ref T value, auto ref JSONValue json) 171 if (!isUnsigned!T && isIntegral!T) { 172 173 if (json.type != JSON_TYPE.INTEGER) { 174 throw new InvalidCastException("Could not convert json " ~ json.toString() ~ " value to type " ~ fullyQualifiedName!T); 175 } 176 177 value = json.integer.to!T; 178 179 return value; 180 } 181 182 /** 183 ditto 184 **/ 185 auto ref fromJson(T)(auto ref T value, auto ref JSONValue json) 186 if (isSomeString!T) { 187 188 if (json.type != JSON_TYPE.STRING) { 189 throw new InvalidCastException("Could not convert json " ~ json.toString() ~ " value to type " ~ fullyQualifiedName!T); 190 } 191 192 value = json.str.to!T; 193 194 return value; 195 } 196 197 /** 198 ditto 199 **/ 200 auto ref fromJson(T : Z[], Z)(auto ref T value, auto ref JSONValue json) 201 if (!isSomeString!T) { 202 203 if (json.type != JSON_TYPE.ARRAY) { 204 throw new InvalidCastException("Could not convert json " ~ json.toString() ~ " value to type " ~ fullyQualifiedName!T); 205 } 206 207 foreach (index, ref el; value) { 208 el = fromJson!Z(value[index], json.array[index]); 209 } 210 return value; 211 } 212 213 /** 214 ditto 215 **/ 216 auto ref fromJson(T : Z[string], Z)(auto ref T value, auto ref JSONValue json) { 217 218 if (json.type != JSON_TYPE.OBJECT) { 219 throw new InvalidCastException("Could not convert json " ~ json.toString() ~ " value to type " ~ fullyQualifiedName!T); 220 } 221 222 auto jsonAssociativeArray = json.object; 223 224 foreach (key, ref el; jsonAssociativeArray) { 225 226 value[key] = fromJson!Z(el); 227 } 228 229 return value; 230 } 231 232 /** 233 ditto 234 **/ 235 T fromJson(T)(auto ref JSONValue json) 236 if (isNumeric!T) { 237 238 T value; 239 240 value.fromJson(json); 241 return value; 242 } 243 244 /** 245 ditto 246 **/ 247 T fromJson(T)(auto ref JSONValue json) 248 if (isSomeString!T) { 249 250 T value; 251 value.fromJson(json); 252 return value; 253 } 254 255 /** 256 ditto 257 **/ 258 T fromJson(T : Z[], Z)(auto ref JSONValue json) 259 if (!isSomeString!T) { 260 if (json.type != JSON_TYPE.ARRAY) { 261 throw new InvalidCastException("Could not convert json " ~ json.toString() ~ " value to type " ~ fullyQualifiedName!T); 262 } 263 264 auto jsonArray = json.array; 265 T array = new Z[jsonArray.length]; 266 array.fromJson(json); 267 268 return array; 269 } 270 271 /** 272 ditto 273 **/ 274 T fromJson(T : Z[string], Z)(auto ref JSONValue json) { 275 276 T assoc; 277 assoc.fromJson(json); 278 return assoc; 279 } 280 }