6

How can I parse JSON in solidity?

The idea is to have a function or similar which is able to parse JSON inside a Solidity contract.

With a simple JSON object (only key value strings, like {'A': 'a', 'B': 'b'}) the solution should be able to transform it to a mapping(string => string).

6

I'll assume that you want to call an external source on which you can't have control and that you use the json() Oraclize datasource in order to get only the right part of the service json that is returned when you call it's URL as indicated in Oraclize Available Datasources documentation.

For now I think you have no way to make Oraclize return anything else than a string. That means that you have to get the returned Json as a string parameter of your oraclize __callback function.

But then, as you ask, you need to parse the json to an array. This would be very costly even if you find a way to do it.

So the short answer would be that what you ask is not possible.

However, let me suggest the following, not totally satisfactory, workarounds. I know it's just workarounds that probably won't fit your needs but I think that what you want to do is not possible for now, so let's just try to go closest as possible from the goal.

Workarounds:

  1. use a proxy website that would be able to request you original service, the one you don't control, and parse the resulting json using whatever your can use as server side language. make it format the result as a single line string with separator (ie. a comma). Then tell Oraclize to query this proxy instead of the original service. Your contract will then get the string that will be more easy and cost efficient to parse and split. You can create a split function based on this Solidity string utils lib. Note that you won't find a split function to split your string in more than 2 slices in this lib but this is a good starting point.
  2. With the Oraclize Json() URL function, you can use XPath to target a value in the JSON result. You could compare the cost of splitting a result string to the cost of calling Oraclize multiple times to target each result item separately. I can't say which is cheaper even if I guess that it really depends of the length of your result items strings.
  3. If you use your contract from a Dapp only, I suggest you to call the original service directly with the client side JS and forget Oraclize, extract values from it and then call a method in which you could pass each value as a parameter. But I guess that if you use Oraclize it's probably that you want your contract to be autonomous.
  • 1
    Thanks for the workarounds, maybe I should change my contract architecture, because at this point I can't solve it like this – arodriguezdonaire Jun 16 '16 at 16:02
6

String parsing will probably be prohibitively expensive inside the EVM. Why do you want to do parsing inside the EVM when you could trivially do it from the outside and pass in the data already in the correct format?

In your specific example if you just want to load a string->string mapping, you could pass in two string arrays as parameters, one being the keys and the second one the values. A simple for cycle could load it up into a Solidity mapping without any parsing overhead.

  • 3
    I need to receive a response from Oraclize.it and it's a JSON, so entering the JSON in parts should cost 2 querys to Oraclize – arodriguezdonaire Jun 16 '16 at 12:38
4

I know this question is rather old, however, I'll add my take nonetheless.

If your JSON is small enough it might be worthwhile to parse it on-chain to avoid the hassle and cost of two or more orchestrated calls to an oracle. I've just released the first version of a JSON parser for Solidity on github: https://github.com/chrisdotn/jsmnSol

If you want to use it you should:

  1. Make sure that the JSON is small. The best way to do that (if you are using oraclize.it) is to find a suitable JSONPath so that the JSON contains only the elements that you are interested in.
  2. Parse the smaller JSON on-chain with the parser. After that you have meta info on the JSON string that allows to locate the elements and get their contents.

A more comprehensive intro is on medium: https://medium.com/@chrisdotn/a-json-parser-for-solidity-9cc73b4b42

So, in essence, what this answer does is to provide a way to use option (2) of Nicolas answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.