Closed rafbgarcia closed 7 years ago
There is nothing built into Oj for that. You could use Scp parsers and convert the keys with the hash_key
method or use the Saj parser and convert and keep track of the keys using it.
hey @ohler55, I've implemented a quick solution and found that it performs worse than deep_transform_keys
and was wondering whether I did something wrong with that, would you mind taking a look?
class Handler < ::Oj::ScHandler
def hash_start
{}
end
def hash_set(h,k,v)
h[k] = v
end
def array_start
[]
end
def hash_key(key)
key.camelize(:lower)
end
def array_append(a,v)
a << v
end
def add_value(v)
p v
end
end
I've used a real response from my server.
require 'benchmark'
json_string = '{"data":{"workingHours":[{"dayName":"Segunda-feira","formattedShifts":"08:00 às 12:00"},{"dayName":"Terça-feira","formattedShifts":"Fechado hoje"},{"dayName":"Quarta-feira","formattedShifts":"Fechado hoje"},{"dayName":"Quinta-feira","formattedShifts":"08:00 às 12:00 - 14:00 às 18:00"},{"dayName":"Sexta-feira","formattedShifts":"08:00 às 12:00"},{"dayName":"Sábado","formattedShifts":"08:00 às 12:00"},{"dayName":"Domingo","formattedShifts":"Fechado hoje"}],"paymentMethodSections":[{"name":"na entrega","paymentMethodGroups":[{"name":"Dinheiro","needsGroup":false,"paymentMethods":[{"id":"93","name":"Dinheiro"}]},{"name":"Cartão de crédito/débito","needsGroup":true,"paymentMethods":[{"id":"94","name":"Crédito - American Express"},{"id":"95","name":"Crédito - Diners"},{"id":"96","name":"Crédito - Elo"},{"id":"97","name":"Crédito - Hipercard"},{"id":"98","name":"Crédito - Mastercard"},{"id":"99","name":"Crédito - Visa"},{"id":"100","name":"Dédito - Elo"},{"id":"101","name":"Dédito - Mastercard"},{"id":"102","name":"Dédito - Visa"}]},{"name":"Vale refeição","needsGroup":true,"paymentMethods":[{"id":"103","name":"Alelo Refeição / Visa Vale"},{"id":"104","name":"Sodexo"},{"id":"105","name":"Ticket Restaurante"}]}]}],"categories":[{"id":"1","name":"Santa Maria","items":[{"id":"1","name":"Santa Maria 10L","description":"","originalPrice":7.0,"hasDiscount":false,"priceWithDiscount":0.0,"currentPrice":7.0,"image":"http://localhost:5000/default_menu_item.svg","complementCategories":[{"id":"1","name":"Garrafão?","required":true,"min":null,"max":null,"multipleChoice":false,"uniqueChoice":true,"complements":[{"id":"2","name":"Não","description":"","price":0.0,"quantity":0},{"id":"1","name":"Sim","description":"","price":1.0,"quantity":0}]},{"id":"129","name":"Raraw","required":false,"min":1,"max":3,"multipleChoice":true,"uniqueChoice":false,"complements":[{"id":"210","name":"Rerer","description":"","price":1.0,"quantity":0}]}]},{"id":"4","name":"Santa Maria 20L + Vasilhame","description":"d","originalPrice":20.0,"hasDiscount":false,"priceWithDiscount":0.0,"currentPrice":20.0,"image":"http://localhost:5000/default_menu_item.svg","complementCategories":[{"id":"128","name":"Escolha os complementos","required":false,"min":1,"max":10,"multipleChoice":true,"uniqueChoice":false,"complements":[{"id":"207","name":"Leite em pó","description":"","price":2.5,"quantity":0},{"id":"208","name":"Chocolate granulado","description":"","price":1.0,"quantity":0},{"id":"209","name":"Granola","description":"","price":1.5,"quantity":0}]}]},{"id":"2","name":"Santa Maria 20L","description":"q","originalPrice":9.0,"hasDiscount":false,"priceWithDiscount":0.0,"currentPrice":9.0,"image":"http://localhost:5000/default_menu_item.svg","complementCategories":[{"id":"130","name":"e","required":false,"min":null,"max":null,"multipleChoice":false,"uniqueChoice":true,"complements":[{"id":"211","name":"ddd","description":"","price":2.22,"quantity":0}]}]},{"id":"3","name":"Santa Maria 10L + Vasilhame","description":"d","originalPrice":15.0,"hasDiscount":false,"priceWithDiscount":0.0,"currentPrice":15.0,"image":"http://localhost:5000/default_menu_item.svg","complementCategories":[]}]},{"id":"7","name":"Pizzas Salgadas","items":[{"id":"37","name":"Pequena","description":null,"originalPrice":0.0,"hasDiscount":false,"priceWithDiscount":0.0,"currentPrice":0.0,"image":"http://localhost:5000/default_menu_item.svg","complementCategories":[{"id":"61","name":"Escolha um sabor","required":true,"min":null,"max":null,"multipleChoice":false,"uniqueChoice":false,"complements":[{"id":"100","name":"Portuguesa","description":null,"price":0.0,"quantity":0},{"id":"101","name":"Calabresa","description":null,"price":0.0,"quantity":0}]},{"id":"60","name":"Escolha a Massa","required":true,"min":null,"max":null,"multipleChoice":false,"uniqueChoice":false,"complements":[{"id":"98","name":"Catupriy","description":null,"price":3.95,"quantity":0},{"id":"99","name":"Integral","description":null,"price":7.5,"quantity":0}]}]},{"id":"38","name":"Grande","description":null,"originalPrice":0.0,"hasDiscount":false,"priceWithDiscount":0.0,"currentPrice":0.0,"image":"http://localhost:5000/default_menu_item.svg","complementCategories":[{"id":"62","name":"Escolha a Massa","required":true,"min":null,"max":null,"multipleChoice":false,"uniqueChoice":false,"complements":[{"id":"102","name":"Catupriy","description":null,"price":3.95,"quantity":0},{"id":"103","name":"Integral","description":null,"price":7.5,"quantity":0}]},{"id":"63","name":"Escolha um sabor","required":true,"min":null,"max":null,"multipleChoice":false,"uniqueChoice":false,"complements":[{"id":"104","name":"Portuguesa","description":null,"price":0.0,"quantity":0},{"id":"105","name":"Calabresa","description":null,"price":0.0,"quantity":0}]}]},{"id":"39","name":"Grande 2 sabores","description":null,"originalPrice":0.0,"hasDiscount":false,"priceWithDiscount":0.0,"currentPrice":0.0,"image":"http://localhost:5000/default_menu_item.svg","complementCategories":[{"id":"64","name":"Escolha a Massa","required":true,"min":null,"max":null,"multipleChoice":false,"uniqueChoice":false,"complements":[{"id":"106","name":"Catupriy","description":null,"price":3.95,"quantity":0},{"id":"107","name":"Integral","description":null,"price":7.5,"quantity":0}]},{"id":"65","name":"Escolha um sabor","required":true,"min":null,"max":null,"multipleChoice":false,"uniqueChoice":false,"complements":[{"id":"108","name":"1/2 Portuguesa","description":null,"price":0.0,"quantity":0},{"id":"109","name":"1/2 Calabresa","description":null,"price":0.0,"quantity":0}]},{"id":"66","name":"Escolha o segundo sabor","required":true,"min":null,"max":null,"multipleChoice":false,"uniqueChoice":false,"complements":[{"id":"110","name":"1/2 Portuguesa","description":null,"price":0.0,"quantity":0},{"id":"111","name":"1/2 Calabresa","description":null,"price":0.0,"quantity":0}]}]}]}],"totalReviewsCount":2,"reviewsWithComments":[{"average":5.0,"comments":"qwdqwdqwd","date":"1 dia","restaurantResponse":"","user":{"firstName":"Rafa","hasAvatar":false,"avatar":"http://localhost:5000/default_avatar.png"}}],"reviewsWithoutComments":[{"average":3.5,"comments":null,"date":"1 dia","restaurantResponse":"","user":{"firstName":"Rafa","hasAvatar":false,"avatar":"http://localhost:5000/default_avatar.png"}}]}}'
json = Oj.sc_parse(Handler.new, json_string)
t1 = Benchmark.measure { 1000.times { Oj.sc_parse(Handler.new, json_string) } }
t2 = Benchmark.measure { 1000.times { json.deep_transform_keys { |key| key.camelize(:lower) } } }
puts "Oj.sc_parse"
puts t1
puts "deep_transform_keys"
puts t2
Oj.sc_parse
6.060000 1.610000 7.670000 ( 6.875817)
deep_transform_keys
4.930000 0.080000 5.010000 ( 4.999562)
Thanks :)
It looks like you are comparing the parsing of a JSON string to running deep_transform_keys
on the result the has already been camelized. Since camelids
and deep_transform_keys
are not part of Ruby core, are you also requiring rails or are you monkey patching Hash and String like rails does?
Anyway, a better comparison would be what you get as a result of using your handler against not using you handler and then running deep_transform_keys
. Use what ever you like to generate the Hash in the case not using your handler.
That code is within a class in a Rails app/
folder.
Gotcha, thanks for the suggestion!
@rafbgarcia how did you solve at the end?
I ended up using deep_transform_keys
anyways, I don't have control over the JSON string in my code because I'm using ruby Graphql, hence I execute the graphql query and receive a Hash back, not a string.
From there I just do
hash.deep_transform_keys { |key| key.camelize(:lower) }
@apuntovanini
What I'd like to do is to convert keys from snake to camel case, right now I'm using
deep_transform_keys
to achieve that, I'm curious if there is an alternative to that :)Thanks