h*C}=      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRS1.2.0.2(c) 2019 Felix PaulusmaMITfelix.paulusma@gmail.com experimental Safe-Inferred")*=)8 safe-json Version profile of a consistent  instance. safe-json,Version of the type checked for consistency. safe-json0All versions in the chain with their type names. safe-json)Profile of the internal consistency of a  instance.N.B.  shows as null instead of a number. safe-json(There is something wrong with versioning safe-jsonProfile of consistent versions  safe-jsonThe  of a + type determines how it can be migrated to.  safe-jsonThis is a wrapper type used migrating backwards in the chain of compatible types.This is useful when running updates in production where new-format JSON will be received by old-format expecting programs.  safe-jsonA simple numeric version id.  has a T< instance and should be declared using integer literals:  = 2 safe-jsonThis is an impenetrable container. A security measure used to ensure  and 1 are never used directly. Instead, always use $ and #. safe-jsonThis instance is needed to handle the migration between older and newer versions.Note that, where ( a)3 migrates from the previous version to the type a, ( (  a))1 migrates from the future version to the type a.Example)Two types that can migrate to each other.(Don't forget to give OldType one of the extended s, and NewType one of the  extension s.)  instance  NewType where type  NewType = OldType  OldType = NewType instance  (  OldType) where type  (  OldType) = NewType  NewType =   OldType  safe-json-The type from which will be migrated to type a safe-json?The migration from the previous version to the current type a. OR, in case of a (  a), the migration from the future version back to the current type a safe-jsonA type that can be converted from and to JSON with versioning baked in, using  to automate migration between versions, reducing headaches when the need arrises to modify JSON formats while old formats can't simply be disregarded. safe-jsonThe version of the type.Only used as a key so it must be unique (this is checked at run-time)Version numbering +doesn't have to be sequential or continuous. The default version is 0 (zero). safe-jsonThe kind specifies how versions are dealt with. By default, values are tagged with version 0 and don't have any previous versions.The default kind is  safe-jsonThis method defines how a value should be serialized without worrying about adding the version. The default implementation uses U$, but can be modified if need be.+This function cannot be used directly. Use # , instead. safe-jsonThis method defines how a value should be parsed without also worrying about writing out the version tag. The default implementation uses V$, but can be modified if need be.+This function cannot be used directly. Use $ , instead. safe-jsonThe name of the type. This is used in error message strings and the  report.+Doesn't have to be defined if your type is W#. The default implementation is %. (cf. &, ', etc.) safe-jsonVersion profile.Shows the current version of the type and all supported versions it can migrate from. safe-jsonUsed when defining  or . safe-json8This is used for types that don't have a version tag.This is used for primitive values that are not tagged with a version number, like Int, Text, [a], etc.But also when implementing  after the fact, when a format is already in use, but you still want to be able to # from it to a newer type or format.N.B.  =  is distinctively different from  = 0#, which will add a version tag with the number 0 (zero), whereas  will not add a  tag. safe-json Returns the  version if the X has one.Y means one of the following:the X is not an Z;$no version field could be found; or,'the version field did not have a number safe-jsonSame as , but requires a   parameter.2encode $ setVersion' (version :: Version Test) val"{\"~v\":0,\"~d\":\"test\"}" safe-json>CAUTION: Only use this function if you know what you're doing. =The version will be set top-level, without inspection of the X!(cf. ) In some rare cases, you might want to interpret a versionless X as a certain type/version. 4 allows you to (unsafely) insert a version field.$If possible, it is advised to use a [ instance instead. (One that doesn't also use $ in its methods!)This might be needed when data sent to an API endpoint doesn't need to implement SafeJSON standards. E.g. in the case of endpoints for third parties or customers. USAGE: {-# LANGUAGE TypeApplications #-} data Test = Test String instance  Test where ... >>> val = \ "test" :: X String "test" >>> ] val ""test"" >>> ] $ 1 @Test val "{"~v":0,"~d":"test"}" >>> parseMaybe $ $  @Test val Just (Test "test")  safe-json>CAUTION: Only use this function if you know what you're doing.(cf. )  removes all the  versioning from a JSON X. Even recursively.This might be necessary if the resulting JSON is sent to a third party (e.g. customer) and the  versioning should be hidden. safe-jsonUsed to define . Base types do not extend any type.  safe-jsonUsed to define  . Extends a previous version.! safe-jsonUsed to define . Types that are !, are extended by a future version and as such can migrate backward from that future version. (cf. ", )" safe-jsonUsed to define . Types that are " are extended by a future version and as such can migrate from that future version, but they also extend a previous version. (cf. !,  )# safe-json#Use this exactly how you would use U from  Data.Aeson8. Though most use cases will probably use one of the  functions from Data.Aeson.Safe.# will add a version tag to the X created. If the X resulting from  (by default the same as U ) is an Z7, an extra field with the version number will be added. Example value: {"type":"test", "data":true} Resulting object: {"!v": 1, "type":"test", "data":true}If the resulting X is not an Z5, it will be wrapped in one, with a version field: Example value: "arbitrary string" Resulting object: {"~v": 1, "~d": "arbitrary string"}0This function does not check consistency of the  instances. It is advised to always  for all 'your instances in a production setting.$ safe-json#Use this exactly how you would use V from  Data.Aeson8. Though most use cases will probably use one of the  functions from Data.Aeson.Safe.$1 tries to find the version number in the JSON X provided, find the appropriate parser and migrate the parsed result back to the requested type using  instances.If there is no version number (that means this can also happen with completely unrelated JSON messages), and there is a # instance in the chain that has  defined as $, it will try to parse that type.N.B. If the consistency of the  instance in *question is faulty, this will always fail.% safe-json%Type name string representation of a nullary type constructor.& safe-json%Type name string representation of a unary type constructor.' safe-json%Type name string representation of a binary type constructor.( safe-json%Type name string representation of a ternary type constructor.) safe-json%Type name string representation of a 4-ary type constructor.* safe-json%Type name string representation of a 5-ary type constructor.^ safe-jsonEasy way to get a printable failure/success report of the internal consistency of a SafeJSON instance.+ safe-json Similar to _, but ed to be used in  definitions, safe-json Similar to `, but ed to be used in  definitions- safe-json Similar to a, but ed to be used in  definitions. safe-json Similar to b, but ed to be used in  definitions/ safe-json Similar to c, but ed to be used in  definitions0 safe-json Similar to d , but uses $= instead of parseJSON to parse the value in the given field.1 safe-json Similar to e , but uses $ instead of parseJSON to maybe parse the value in the given field.2 safe-json Similar to f , but uses $ instead of parseJSON to maybe parse the value in the given field.3 safe-json Similarly to g , but uses # instead of toJSON to convert the value in that key-value pair.h safe-json*This instance explicitly doesn't consider 2, since it is an exception in almost every sense.i safe-json safe-jsonTry to decode a file to a  value.? safe-jsonTry to decode a file to a  value.@ safe-jsonTry to decode a file to a 0 value. Produces an error message on failure.A safe-jsonTry to decode a file to a 0 value. Produces an error message on failure.B safe-json Encode a  value to a file. #$+,-./0123 !"%&'()*[ZX\g_a`bcdef45678B9:;<>?@A=456789:;<=>?@AB(c) 2019 Felix PaulusmaMITfelix.paulusma@gmail.com experimental Safe-Inferred "/<C safe-json/Constraints for migrating from a future versionD safe-json1Constraints for migrating from a previous versionE safe-jsonUseful in test suites. Will fail if anything in the chain of your types is inconsistent.Example usage: testConsistency @MyTypeF safe-jsonUseful in test suites. Will fail if anything in the chain of your types is inconsistent.G safe-jsonTests that the following holds:0Just a == parseMaybe safeFromJSON (safeToJSON a)H safe-jsonTests that the following holds for all a:0Just a == parseMaybe safeFromJSON (safeToJSON a)I safe-json'Tests that the following holds for all a:0Just a == parseMaybe safeFromJSON (safeToJSON a)Example usage: testRoundTripProp @MyType sJ safe-json1Migration test. Mostly useful as regression test.First argument is the older type which should turn into the second argument after migrating using .:Just (migrate a) == parseMaybe safeFromJSON (safeToJSON a)K safe-json Similar to J , but using Migrate (Reverse a).The first argument here is the newer type, which will be migrated back to the expected second argument (older type).Just (unReverse $ migrate a) == parseMaybe safeFromJSON (safeToJSON a)L safe-jsonOperator synonymous with JM safe-jsonOperator synonymous with KN safe-jsonThis test verifies that direct migration, and migration through encoding and decoding to the newer type, is equivalent.O safe-json Similar to N, but tests the migration from a newer type to the older type, in case of a  (  a) instanceP safe-jsonThis test verifies that direct migration, and migration through encoding and decoding to the newer type, is equivalent for all a.:Just (migrate a) == parseMaybe safeFromJSON (safeToJSON a)Q safe-jsonThis test verifies that direct migration, and migration through encoding and decoding to the newer type, is equivalent for all a.:Just (migrate a) == parseMaybe safeFromJSON (safeToJSON a)Example usage: (migrateRoundTripProp @NewType @OldType sR safe-json Similar to Q, but tests the migration from a newer type to the older type, in case of a  (  a) instance.Just (unReverse $ migrate a) == parseMaybe safeFromJSON (safeToJSON a)S safe-json Similar to Q, but tests the migration from a newer type to the older type, in case of a  (  a) instance.Just (unReverse $ migrate a) == parseMaybe safeFromJSON (safeToJSON a)Example usage:8Please also note the reversing of the type applications. /migrateReverseRoundTripProp @OldType @NewType sEFJKLMGNODCIQSHPREFJKLMGNODCIQSHPRL1M1  Safe-Inferred"<      !"#$%& '()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW XYZ[\Z]^ _`Zab cdZaeZ]fZagZhiZ]jZ]kZ]lZ]mZ]nZ]oZ]pZ]qZ[rst Xuvwxyz{|}~ZZaZaZaZ]Z]ZaZ]Z]Z]Z]ZZZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaZaeZaZaZaZaZZZ]Z]Z]Z]Z]Z]Z]Z]Z]Z]Z]Z]Z]Z]Z]Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[ZZZ]Z[ZaZaZaZaZaZaZZZ]Z]Z]Z]Z]Z]Z]Z]Z]Z]Z]Z]Z[Z[Z[Z[Z[Z[Z[Z[Z[Z[ZZZZZZZhZhZaZaZa        (safe-json-1.2.0.2-3kzLoiboqZdDhjXd35uMKPData.SafeJSON.Test Data.SafeJSONData.Aeson.Safe safe-jsonData.SafeJSON.InternalencodetestConsistencydecodePaths_safe_jsonbase Data.ProxyProxyProfileVersionsprofileCurrentVersionprofileSupportedVersionsProfileInvalidProfileKindReverse unReverseVersion ContainedMigrate MigrateFrommigrateSafeJSONversionkindsafeTosafeFromtypeName objectProfilecontain noVersion getVersion setVersion' setVersion removeVersion extension extended_baseextended_extension safeToJSON safeFromJSON typeName0 typeName1 typeName2 typeName3 typeName4 typeName5containWithObjectcontainWithArraycontainWithTextcontainWithScientificcontainWithBool.:$.:$?.:$!.=$decode' eitherDecode eitherDecode' decodeStrict decodeStrict'eitherDecodeStricteitherDecodeStrict' encodeStrictdecodeFileStrictdecodeFileStrict'eitherDecodeFileStricteitherDecodeFileStrict' encodeFileTestReverseMigrate TestMigratetestConsistency' testRoundTriptestRoundTripProp'testRoundTripProp testMigrationtestReverseMigration<=?>=?migrateRoundTripmigrateReverseRoundTripmigrateRoundTripProp'migrateRoundTripPropmigrateReverseRoundTripProp'migrateReverseRoundTripPropGHC.NumNum$aeson-2.2.3.0-KMRiqJCg2doDycuGNq2s96Data.Aeson.Types.ToJSONtoJSONData.Aeson.Types.FromJSON parseJSONData.Typeable.InternalTypeableData.Aeson.Types.InternalValue GHC.MaybeNothingObjectFromJSONString Data.Aeson mkProfile withObject withArraywithTextwithScientificwithBool.:.:?.:!.=$fArbitraryVersion $fNumVersion fromInteger$fShowProfileVersions$fSafeJSONProduct $fSafeJSONSum$fSafeJSONCompose$fSafeJSONKeyMap$fSafeJSONList Consistency Consistent NotConsistentExtendedExtendsBase unVersion unsafeUnpackinternalConsistencyliftV castVersion versionFielddataVersionField dataFieldconstructParserFromVersionnoVersionPresentshowVshowVscheckConsistencycomputeConsistencyisObviouslyConsistentavailableVersions invalidChainproxyFromVersion kindFromProxyversionFromProxyversionFromKindgetForwardKind withContainedfromGenericVectortoGenericVectorbytestring-0.11.5.2Data.ByteString.Lazy.Internal ByteStringData.ByteString.Internal.TypetoStrictData.Aeson.Types.GenericOneResultSuccessError parseJSONList omittedFieldArray FromJSON1 liftParseJSONliftParseJSONListliftOmittedFieldData.Aeson.KeyKeyZeroAesonExceptionJSONKeyOptions keyModifier SumEncoding TaggedObject UntaggedValueObjectWithSingleField TwoElemArray tagFieldNamecontentsFieldNameOptionsfieldLabelModifierconstructorTagModifierallNullaryToStringTagomitNothingFieldsallowOmittedFields sumEncodingunwrapUnaryRecordstagSingleConstructorsrejectUnknownFields DotNetTimefromDotNetTimeBoolNumberNullJSONPathData.Aeson.Encoding.InternalSeriesEncoding FromJSON2liftParseJSON2liftParseJSONList2liftOmittedField2 GFromJSONKeyFromJSONKeyFunctionFromJSONKeyCoerceFromJSONKeyTextFromJSONKeyTextParserFromJSONKeyValue FromJSONKey fromJSONKeyfromJSONKeyListFromArgs GFromJSONToJSON2 liftToJSON2liftToJSONList2liftToEncoding2liftToEncodingList2liftOmitField2ToJSON1 liftToJSONliftToJSONListliftToEncodingliftToEncodingList liftOmitField GToJSONKeyToJSONKeyFunction ToJSONKeyTextToJSONKeyValue ToJSONKey toJSONKey toJSONKeyList KeyValueOmit.?=explicitToFieldOmitKeyValueexplicitToFieldToJSON omitField toEncoding toJSONListtoEncodingListToArgsGToJSON'Data.Aeson.Types.Class GToEncodingGToJSONgenericFromJSONKeygenericToJSONKeyobjectdefaultOptionsdefaultTaggedObjectdefaultJSONKeyOptionscamelTo2 fromEncodingpairsparseIndexedJSONgenericParseJSONgenericLiftParseJSON parseJSON1 omittedField1 parseJSON2 omittedField2withEmbeddedJSONfromJSON.:?=.:!=.!= genericToJSONgenericLiftToJSONgenericToEncodinggenericLiftToEncodingtoJSON1 toEncoding1 omitField1toJSON2 toEncoding2 omitField2Data.Aeson.TypesfoldableData.Aeson.DecodingthrowDecodeStrict throwDecodedecodeStrictTexteitherDecodeStrictTextthrowDecodeStrictText throwDecode'throwDecodeStrict'Parser parseEither parseMaybe getBinDir getLibDir getDynLibDir getDataDir getLibexecDirgetDataFileName getSysconfDir