Need help to understand the function of the resolver/resolveSchema method

I was going through the code, mainly the core module. I encountered something which I was not able to understand clearly.

Intesters/index.js and I could see that we have called resolver/resolveSchema method from 2-3 methods e.g schemaSubPathMatches, schemaMatches etc. But I think, we can be certain at that time that schema does not contain any refs and can skip this whole null checking and the long recursive method.

Is there any specific case where we are not resolving $refs at the beginning(maybe as a first step) and we need to resolve refs at the runtime?

Why don’t we simply resolve the whole schema in one go and pass a flattened schema to the main renderer component?

[original thread by shivgarg5676]

Hi @shivgarg5676, sadly ref resolving is a very complex topic.

Note that our current code regarding resolving is a little ambiguous, as we have multiple resolving concepts which are not named distinctly enough. We have resolving of $refs within JSON schema, resolving of scopes of ui schemas and resolving the data path for controls to modify. Additionally we use a subschema concept for the renderers, as they should only get the parts of the schemas they are interested in / responsible for. These subschemas also need to be “resolved”, including special cases like oneOf. Therefore any resolve or similar named method you can find could refer to any of these concepts, please keep that in mind.

Regarding $refs:

If your use case is “simple enough” that you can get rid off most (or all) of the $refs beforehand you could just do it yourself in your app by resolving the schema and only then giving it to JSON Forms :wink: (Note that in our experience we never encountered any problems with schemas structured like that, so you should be able to just give it to JSON Forms without any problem)

Two topics to think about:

  • You can’t get rid off all $refs by design of JSON schema itself. As recursive and circular reference structures are allowed you can never get rid of all the $refs. Either your resolver runs in an endless loop or you end up with a JSON object structure which references itself, with which for example Ajv crashes. So you will end up at least with all the recursive / circulars $refs left and need to handle them dynamically whenever you encounter them.

  • Ref resolving is quite an expensive operation, especially as you can also point to remote sources. However the schema / ui schema combination you want to render might only use a small subset of the schema, involving little or no ref resolving. (For example when you use categorization and have a use case where only one category will be used). So ideally instead of preemptively resolving whatever $ref exists in the schema it would be great to only resolve what is actually needed.

We are not so happy with the current state of resolving in JSON Forms in which we mostly resolve $refs globally (see mapStateToJsonFormsProps), but trigger the resolving too often (we cache much of it away, however that is also not too elegant :wink: ). We also have problems in cases where we are working with subschemas, but they are pointing outside their scope (for example to a $defs block). Therefore we are currently refactoring our whole ref resolving approach, making it much more explicit instead of an afterthought. You can see the current state of the refactoring here: Async ref resolving by edgarmueller · Pull Request #1505 · eclipsesource/jsonforms · GitHub

Does this answer your question? Did you have a specific use case in mind? We welcome any input to this topic :wink:


This was really helpful explanation. Thanks for the update.