{"id":18847674,"url":"https://github.com/everythingfunctional/rojff","last_synced_at":"2025-07-19T12:32:46.028Z","repository":{"id":146073938,"uuid":"476481761","full_name":"everythingfunctional/rojff","owner":"everythingfunctional","description":"Return of JSON for Fortran: a much more performance oriented take on a json library","archived":false,"fork":false,"pushed_at":"2023-03-21T15:21:44.000Z","size":343,"stargazers_count":8,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-14T08:09:48.111Z","etag":null,"topics":["fortran","json","json-parser"],"latest_commit_sha":null,"homepage":"","language":"Fortran","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/everythingfunctional.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2022-03-31T21:19:03.000Z","updated_at":"2023-07-30T22:55:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"6ca9b07b-89af-472b-8981-e6e844cb50de","html_url":"https://github.com/everythingfunctional/rojff","commit_stats":{"total_commits":126,"total_committers":4,"mean_commits":31.5,"dds":0.07936507936507942,"last_synced_commit":"9f68e5aa4c12b32720d4224f1ac279bfd7d77b93"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/everythingfunctional%2Frojff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/everythingfunctional%2Frojff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/everythingfunctional%2Frojff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/everythingfunctional%2Frojff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/everythingfunctional","download_url":"https://codeload.github.com/everythingfunctional/rojff/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248843867,"owners_count":21170492,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fortran","json","json-parser"],"created_at":"2024-11-08T03:09:12.574Z","updated_at":"2025-04-14T08:09:53.476Z","avatar_url":"https://github.com/everythingfunctional.png","language":"Fortran","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rojff: Return of JSON (for Fortran)\n\n[![pipeline status](https://gitlab.com/everythingfunctional/rojff/badges/main/pipeline.svg)](https://gitlab.com/everythingfunctional/rojff/commits/main)\n\nWith an interface inspired by [jsonff](https://gitlab.com/everythingfunctional/jsonff),\nthe data semantics and parser are redesigned to allow for high performance.\n\nA full set of procedures are provided for either combination of two orthogonal aspects of constructing a JSON data structure:\n\n* Functional style constructors enabling single-expression construction **vs** move semantics to avoid data copying\n* Check for possible errors **vs** avoid error checks\n\nFunctions with the same name as the type (or `unsafe` substituted for `_t` to indicate avoidance of error checks) are provided for the functional style.\nSubroutines named `create_*` or `move_into_*` are provided for avoiding data copying.\n\nNo error checking is required for values of type `json_null_t`, `json_bool_t`, `json_integer_t`, or `json_number_t`, so no fallible types or unsafe procedures are provided for them.\nConstruction of these types done like:\n\nfunctional | move\n-----------|------\n`json_null_t()` | `create_json_null(null_var)`\n`json_bool_t(.true.)` | `create_json_bool(bool_var, .true.)`\n`json_integer_t(1)` | `create_json_integer(int_var, 1)`\n`json_number_t(3.14d0)` | `create_json_number(num_var, 3.14d0)`\n\nThe construction of a string can check that it is a valid json string (i.e. contains only proper escape sequences and no unescaped quotes).\nThe construction of an object can check that no duplicate keys are present.\nThe construction of strings, arrays and objects can be accomplished via the following different methods.\n\nfunctional unsafe | function with errors | move unsafe | move with errors\n------------------|----------------------|-------------|-----------------\nN/A               | `fallible_json_value_t(val)` | N/A | `move_into_fallible_json_value(maybe_val, val)`\n`json_string_unsafe(string)` | `fallible_json_string_t(string)` | `create_json_string_unsafe(str, string)` | `create_fallible_json_string(maybe_str, string)`\n`json_element_t(val)` | `fallible_json_element_t(maybe_val)` | `move_into_element(elem, val)` | `move_into_fallible_element(maybe_elem, maybe_val)`\n`json_array_t(elems)` | `fallible_json_array_t(maybe_elems)` | `move_into_array(array, elems)` | `move_into_fallible_array(maybe_array, maybe_elems)`\n`json_member_unsafe(key, val)` | `fallible_json_member_t(key, val)` | `move_into_member_unsafe(member, key, val)` | `move_into_fallible_member(maybe_member, maybe_key, maybe_val)`\n`json_object_unsafe(members)` | `fallible_json_object_t(maybe_members)` | `move_into_object(obj, members)` | `move_into_fallible_object(maybe_obj, maybe_members)`\n\nFull examples of constructing the same data structure all four different ways are provided in the [construction method test](test/construction_method_test.f90).\nIt is recommended to start with the functional style with error checking.\nIf sufficient testing has been performed, and any strings will not come from user input, then switching to the unsafe methods can be considered.\nIf sufficient evidence has been seen that performance is a problem, then it may be beneficial to switch to the `create_*` and `move_*` methods.\n\nOnce constructed, JSON values can be converted to string representation in either compact or expanded, human-readable formats.\nAdditionally, procedures are provided (`parse_json_from_string` and `parse_json_from_file`)\nthat parse contents into a JSON data structure.\nIt also provides reasonable error messages in the event the contents do not contain valid JSON.\n\nA string generated from a valid JSON data structure is guaranteed to be able to be parsed by the parser into exactly the same data structure.\nNote that a data structure parsed from a string is not necessarily guaranteed to produce exactly the same string,\nsince formatting is not important to JSON data.\n\nUsing rojff\n------------\n\nThis section provides some examples to use rojff in your project.\nA detailed references on the functionality of rojff is available in\n[the developer documentation](https://everythingfunctional.gitlab.io/rojff).\n\n\n### Reading and writing a JSON\n\nTo create a simple reader and writer for JSON three steps are usually required.\nA small and concise example to read JSON from a file and pretty print it is given here.\n\n```fortran\nprogram example\n    use iso_varying_string, only: char\n    use rojff\n\n    implicit none\n\n    type(fallible_json_value_t) :: parsed_json\n\n    parsed_json = parse_json_from_file('index.json')\n\n    if (parsed_json%failed()) then\n        error stop char(parsed_json%errors%to_string())\n    end if\n\n    print *, parsed_json%value_%to_expanded_string()\nend program\n```\n\nA JSON document can be parsed from a string with the `parse_json_from_string` function\nor by reading a file with the `parse_json_from_file` function.\nBoth functions return an instance of a `fallible_json_value_t` type\nrepresenting a union of an `error_list_t` and a `json_value_t`.\nTo verify the correctness of the parsed JSON the `fallible_json_value_t` can be checked with the `%failed()` method.\nIn case of failure the `error_list_t` component can be accessed via `%errors`\nand should be handled appropriately by the caller.\n\nIf the JSON document was correct the `json_value_t` can be accessed via `%value_` and processed further.\nSerialization with the `%to_expanded_string()` or `%to_compact_string()` method returns a `character(len=:), allocatable`.\nSerialization to a file can be performed with the `%save_expanded_to(file_name)` or `%save_compactly_to(file_name)` methods.\nIf there is a chance the file may already exist, the `status=\"replace\"` optional argument should be included.\n\nThe *literal* value (e.g. null) is identified by its type alone and contains no data.\nThe scalar values (e.g. bool, string, integer and number) contain their values,\nwhich can be accessed via `%bool`, `%string`, and `%number` respectively.\nThe composite values (e.g. object and array), contain zero or more elements, which can be accessed via the `get` type bound procedures.\nRetrieving an element from an object requires a string (the key), and from an array requires an integer (the index).\nBoth procedures return a `fallible_json_value_t`, as it would be possible to ask for an element that does not exist.\nAdditionally, one can access the whole array of values from a json array as an array of `json_element_t` objects via `%elements`.\nOne can get arrays of keys (as `varying_string`s) and values (as `json_element_t`s) from an object,\nwhich are guaranteed to be returned in matching order, via `get_keys` and `get_values`.\n\n### Real World Usage For Inputs\n\nAn example of parsing a JSON string and retrieving a value by its key can be found in `example/get_value`. It also includes basic error handling.\n\nIn most cases, however, you're going to have inputs in JSON format corresponding to derived types in your program.\nThe example in `example/custom_types` illustrates how this might be done for a triangle area calculator.\nIt allows for easy composition and reuse, while still handling all the possible errors that might occur with regards to erroneous input.\nAny errors that occur trying to access a component of the JSON are propagated through.\nAny mismatches in the expected types of the data are able to generate meaningful errors.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feverythingfunctional%2Frojff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feverythingfunctional%2Frojff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feverythingfunctional%2Frojff/lists"}