{"id":18924092,"url":"https://github.com/applesack/over-thinking","last_synced_at":"2025-07-27T00:35:26.391Z","repository":{"id":134419114,"uuid":"526622003","full_name":"applesack/over-thinking","owner":"applesack","description":"leetcode刷题代码库，以及一些算法笔记","archived":false,"fork":false,"pushed_at":"2023-10-25T03:31:12.000Z","size":467,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-12-31T17:30:52.520Z","etag":null,"topics":["algorithms","java","leetcode"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/applesack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-19T13:37:48.000Z","updated_at":"2023-04-07T02:57:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"b84f40c3-0c15-4ea0-8065-69a2d5124abf","html_url":"https://github.com/applesack/over-thinking","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/applesack%2Fover-thinking","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/applesack%2Fover-thinking/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/applesack%2Fover-thinking/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/applesack%2Fover-thinking/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/applesack","download_url":"https://codeload.github.com/applesack/over-thinking/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239921877,"owners_count":19718842,"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":["algorithms","java","leetcode"],"created_at":"2024-11-08T11:05:44.510Z","updated_at":"2025-02-20T21:57:58.772Z","avatar_url":"https://github.com/applesack.png","language":"Java","readme":"# over-thinking\n\n一些算法笔记，以及随手写的小玩具\n\n\n\n## Json解析器\n\n使用栈和有限状态机实现的`json`解析器，不使用递归所以不受`json`结构深度的影响，且解析时每次只读取一个字符，不需要对数据源随机读写，适用于内存受限的场景。\n\n### 算法描述\n\n从一个案例开始:\n\n```json\n\\n {\n    \"abc\": [true, \\t null, {}, x] \\t\n} \"hello world\"\n```\n\n首先`json`的类型只能是`null, object, array, string, true, false, number`之中的一种，而拿到一个`json`的时候并不能确定它是什么类型的，所以一开始假定当前json的类型为`unknown`。\n\n如果当前类型为`unknown`，那么读到的第一个字符就可以指明这个`json`的类型，当然会跳过一些空白符，如`' ', '\\t', '\\n', '\\r'`，这里有以下设定\n\n|       开始字符        | 推断类型  |\n| :-------------------: | :-------: |\n|           {           |  Object   |\n|           [           |   Array   |\n|           \"           |  String   |\n|       -， digit       |  Number   |\n|           n           |   Null    |\n|           t           |   True    |\n|           f           |   False   |\n| ' ', '\\r', '\\t', '\\n' |  Unknown  |\n|         other         | Exception |\n\n当前`json`有了具体的类型，接下来读取的字符就会进入到对应类型的解析逻辑中，这些类型从解析方法上可以分为两类：第一种是容器类型，即类型可以嵌套包含其他类型，如`object`和`array`；第二种是普通类型，不能嵌套其他类型的类型。\n\n\n\n**栈与状态机**\n\n为了解析包含嵌套结构的数据类型，引入了栈的概念，当未开始进行解析的时候，栈中有一个元素且类型为`unknown`，表示当前`json`中有一个未知元素，当解析到第一个非空字符`{`，可以推断当前`json`的类型为`object`，于是将当前栈顶的元素类型修改为`object`，从第二个字符开始，进入解析`object`的逻辑，这里列出解析`object`的状态\n\n| 当前状态 |  次级状态  |\n| :------: | :--------: |\n|    键    | 冒号，结束 |\n|   冒号   |     值     |\n|    值    | 逗号，结束 |\n|   逗号   |     键     |\n|   结束   |    结束    |\n\n解析`object`的默认状态为**键**，即当前如果读到一个非空字符，那么这个字符只能是`\"`或者`}`, 其余情况视为异常。\n\n![解析object](docs/json/parse_object_1.png)\n\n如果读取的是一个字符串，那么会将一个字符串类型的元素压到栈顶，当字符串解析完成后，首先将栈顶的值保存，然后将栈顶弹出栈，最后将字符串的值传递到当前的栈顶，即`object`。而`object`会根据当前的状态来将值插入键或者值，比如当前状态为*键*，即传入的值会保存到键中，然后当前状态转换为*冒号*，即下一个非空字符必须是冒号。\n\n暂时写到这里。\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapplesack%2Fover-thinking","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapplesack%2Fover-thinking","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapplesack%2Fover-thinking/lists"}