Preprocessing certain fields in a schema

Hello,

I’d like to validate some data coming in from Google Datastore. Unfortunately some types there are wrapped in a StringIO and so I need to somehow preprocess them. Specifically calling .properties.to_h on a response gives me a hash with an items array that’s an array of hashes within a StringIO instance. So what I’d like to do is call JSON.parse(input.string) to unwrap it and then I’d like to validate each hash within that. I tried doing that with a custom type DatastoreArrayBlob = Array.constructor { |input| ::JSON.parse(input.string) }, but then I can’t seem to be able to validate that inside the contract:

class MyContract < Dry::Validation::Contract
  json do
    required(:items).value(Types::DatastoreArrayBlob).each do
      hash do
        required(:code).filled(:string)
      end
    end
  end
end

For some reason this always clears the code so in result I’m getting (...):items=>[{}]} errors={:items=>{0=>{:code=>["is missing"]} Now if I remove the each call I can see that the type constructor works just fine as items indeed has hashes with code keys, but for some reason that .each call clears them. Is there perhaps another way to write that for such custom arrays?

This should work. Could you provide a reproduction script/test?

@solnic Sure, hope this works: https://github.com/DawidJanczak/dry-validation-custom-array-type/blob/master/test.rb

@DawidJanczak damn, that’s a bug - please report it under dry-schema project. As a workaround you can use JSON.parse(input.string, symbolize_keys: true).