【问题标题】:How to load a json folder into Javascript?如何将 json 文件夹加载到 Javascript 中?
【发布时间】:2019-11-13 01:24:37
【问题描述】:

我想加载(需要)一个包含基于其文件的引用的 json 模式的文件夹。

换句话说,我有

Schema1: 
{ //Schema stuff ....
    "$ref": "./json_schema2_file.json#someElement"
}

在同一文件夹中的另一个文件中:

Schema2
{//Schema stuff...
"$id": "/someElement"
}

这些 Schema 位于单独的文件中,现在应该加载到 JS 中以针对 json 对象进行验证。 但是,文件夹内的引用应该仍然有效。

这就是为什么我的问题是,是否以及如何加载一个充满 json 文件的文件夹而不引用中断。

这些模式将被此库用于验证 json 对象:https://github.com/tdegrunt/jsonschema 我个人将 Node 与 Angular 一起使用,因此使用 fs 仅适用于节点,但这只是一个开始。

【问题讨论】:

  • 您的参考资料不太正确。我现在无法形成完整的答案,但请查看库文档以了解如何在github.com/tdegrunt/… 上执行此操作
  • 您是指在 tdgrunt 库中的引用还是对 json 模式的引用?因为我创建了一个包含 json 模式的文件夹,其中引用应该是正确的,但是如果我没看错的话,tdgrunt 库有不同的引用方式。
  • 您为给定的 $ids 编写了错误的 JSON 架构引用。 JSON Schema 本身不知道单个文件或文件系统本身,而是使用 URI 解析协议。想象你的 $ref 是一个 HTML 链接 href,它只知道它所在页面的当前 URL。这有帮助吗?
  • 我跟着这个:swagger.io/docs/specification/using-ref 不过也许我必须再放一个点。 Webstorm 找到了它,所以我认为它是正确的。我用 ./ ../ 和没有 / 进行了测试
  • 呃,这就解释了为什么我们会看到这么多问题。如果 $id 反映了可访问的 URL,并且所有模式都在所述 URL 和相对路径中提供,并且您使用的库支持(通常带有标志)远程 http 解析,则相对位置仅适用于自动远程引用。

标签: node.js json angular jsonschema


【解决方案1】:

通常,JSON Schema 解析器(包括我维护的 jsonschema 包)不会自动恢复加载引用。您只需要提供具有架构的附加文件:

var Validator = require('jsonschema').Validator;
var v = new Validator();
v.addSchema(require('./json_schema.json'), 'http://example.com/json_schema.json');
v.addSchema(require('./json_schema2.json'), 'http://example.com/json_schema2.json');

不要忘记为您的架构提供完整的 URI,否则它们可能无法在应用程序之间一致地工作。

如果您想自动导入引用,jsonschema 包提供了已知架构的列表,而 Validator#unresolvedRefs 属性中没有定义。移出此堆栈并使用Validator#addSchema 导入引用:

async function importUnresolved(){
    for(var uri; uri = v.unresolvedRefs.shift();){
        // where `get` is some resolver that downloads the schema
        schema = await get(uri);
        if(!schema) throw new Error(`Could not dereference JSON schema: <${uri}>`);
        v.addSchema(schema, uri);
    }
}

【讨论】:

  • 这对特定元素的引用是否有效?我相信您可以获得该架构的 json 文件,如果我在架构中引用定义,它仍然可以解决吗? ./folder/schema.json#myElement 之类的东西? get 函数必须对 #myElement 部分进行切片才能获取文件并读取它,但是 v.addSchema(schema, ./folder/schema.json#Element) 是否可以解析定义中的元素(其他类型的嵌套内容)?很抱歉,但我真的对不同上下文中所有不​​同类型的 uri 以及它们能做什么和不能做什么感到困惑。
【解决方案2】:

在您的 Node 后端,require 可用于导入 JSON 文件,就好像它是一个普通的 JavaScript 文件一样:

// data.json
{ "hello": "world" }

// main.js
const data = require('./data.json');
console.log(data); // { hello: 'world' }

对于您的 Angular 前端,这取决于您如何构建捆绑包,但通常使用 import data from './data.json' 应该会产生相同的结果(如 this question 中所述)。


现在问题来了:如果您的架构位于多个 JSON 文件中,您该怎么办?

requireimport 本身都不会花时间解析 $ref$id 属性并将所有内容捆绑到单个 JS 对象中。似乎没有任何简单的本地方法来解析所有内容,幸运的是 NPM 包 json-schema-ref-parser 正是这样做的!它可以在您的用例中使用:

// foo.schema.json 
{
    "type": "object",
    "properties": {
        "bar": {
            "$ref": "./bar.schema.json"
        }
    }
}

// bar.schema.json 
{
    "type": "number"
}

// main.js 
const parser = require('json-schema-ref-parser');
parser.dereference('foo.schema.json', (err, schema) => console.log(schema));
// logs: { type: 'object', properties: { bar: { type: 'number' } } }

【讨论】:

  • 这会加载一个 json 文件。然而,在这个 json(模式)中,有一些引用假定他们的文件夹是根文件夹。如果我按照建议需要 json 文件,第一个 ref 会引发错误。
  • SchemaError: no such schema #meta> 准确地说。 meta是这样引用的:"$ref": "./meta_nlp_schema.json#meta",而id是:"$id": "/meta",表示引用坏了或者我做错了^^ .
  • 完成!我使用您需要的用例处理编辑了我的答案。现在可以了吗?
  • 它应该可以工作。但是我仍然遇到了这里描述的那个库的问题:github.com/APIDevTools/json-schema-ref-parser/issues/130 但如果可以解决,我认为它应该可以解决问题。换句话说,你的答案应该是我的问题的答案。谢谢。
【解决方案3】:

1.使用json解析器编写json内容,避免拼写错误。

 {
     "quiz": 
     [
         {
             "question": "Question 1",
             "a": "Answer a",
             "b": "Answer b",
             "c": "Answer c",
             "correct": "a"
         },
         {
             "question": "Question 2",
             "a": "Answer a",
             "b": "Answer b",
             "c": "Answer c",
             "correct": "b"
         },
         {
             "question": "Question 3",
             "a": "Answer a",
             "b": "Answer b",
             "c": "Answer c",
             "correct": "c"
         }
     ]
 }

2.将 json 保存在与 js 脚本相同的文件夹中。我将我的文件命名为 questions.json。 3.用$.getJSON加载json数据。以下示例是将问题从 json 加载到 allQuestions 数组的完整脚本。

var allQuestions = new Array();
    
function loadQuestions() {
    $.getJSON('question.json', function (data) {
        allQuestions = data.quiz;
    }).error(function(){
            console.log('error: json not loaded');
        });
    });
}

4.现在你的 json 数据在 allQuestions 数组中,你可以访问它,例如:

var currentQuestion = allQuestions[0].question;
var answerA         = allQuestions[0].a; 

使用 .done 回调 请记住,$getJSON 是异步运行的。这样的实现不是最好的主意:

loadQuestions();
printQuestion(allQuestions[0]); 

有可能在调用 printQuestion 的那一刻,JSON 还没有加载,allQuestions 的大小为 0。为确保在 JSON 完全加载后完成某些操作,请使用 .done 回调。

var allQuestions = new Array();
    
function loadQuestions() {
    $.getJSON('question.json', function (data) {
        allQuestions = data.quiz;
    })
    .error(function() {
        console.log('error: JSON not loaded'); 
    })
    .done(function() {
        console.log( "JSON loaded!" );
        printQuestion(allQuestions[0]); 
    });
}

【讨论】:

  • 这太荒谬了。这也意味着 HTTP 请求以及在这方面必须对服务器和开发/生产应用程序结构差异进行编码的所有其他内容。只需使用require/import...
  • 我看不出这是如何回答这个问题的,这是 JSON Schema 特有的:json-schema.org
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-22
  • 1970-01-01
  • 2013-05-30
  • 1970-01-01
  • 2019-12-29
  • 2013-07-11
  • 1970-01-01
相关资源
最近更新 更多