【问题标题】:Loading JSON Without an HTTP Request在没有 HTTP 请求的情况下加载 JSON
【发布时间】:2017-11-02 22:16:23
【问题描述】:

我正在使用 Angular 4、NPM、Node.js 和 Angular CLI 开发一个项目。

我有一个非常不寻常的需要,即在没有 HTTP 请求的情况下将 JSON 加载到 Angular 服务中(使用 @Injectable),即它总是作为包的一部分在本地加载,而不是从服务器检索。

到目前为止,我发现的所有内容都表明您要么必须修改项目的 typings.d.ts 文件,要么使用 HTTP 请求从 /assets 文件夹或类似文件夹中检索它,这对我来说都不是一个选项。

我想要完成的是这个。给定以下目录结构:

/app
    /services
        /my-service
            /my.service.ts
            /myJson.json

我需要使用@Injectablemy.service.ts 服务来加载JSON 文件myJson.json。对于我的特殊情况,my.service.ts 文件旁边将有多个 JSON 文件都需要加载。

澄清一下,以下方法对我不起作用:

使用 HTTP 服务从资产加载 JSON 文件

网址:https://stackoverflow.com/a/43759870/1096637

摘录:

// Get users from the API
return this.http.get('assets/ordersummary.json')//, options)
    .map((response: Response) => {
        console.log("mock data" + response.json());
        return response.json();
    }
    )
    .catch(this.handleError);

修改 typings.d.ts 以允许加载 JSON 文件

网址:https://hackernoon.com/import-json-into-typescript-8d465beded79

摘录:

解决方案:使用通配符模块名称 在 TypeScript 版本 2+ 中,我们可以在模块名称中使用通配符。在您的 TS 定义文件中,例如typings.d.ts,可以加这行:

declare module "*.json" {
    const value: any;
    export default value;
}

然后,您的代码将像魅力一样工作!

// TypeScript
// app.ts
import * as data from './example.json';
const word = (<any>data).name;
console.log(word); // output 'testing'

问题

有没有其他人有任何想法将这些文件加载​​到我的服务中而不需要这些方法中的任何一种?

【问题讨论】:

  • 当您谈到service 时,您指的是网络服务还是角度服务?
  • Angular 服务。
  • “与服务在同一目录中”是什么意思?你的意思是服务中有一个变量保存了 JSON 对象?
  • @StephenRios 刚刚注意到你用service.ts 更新了问题,你正在使用这个Angular 2 吗?如果是这样,请更新您的问题以反映这一点。
  • 我也很困惑,service.ts 解决了歧义。 AngularJs 是什么,Angular2 是别的东西

标签: json angular angular2-services


【解决方案1】:

如果直接调用 json 会报错,但一个简单的解决方法是为所有 json 文件声明类型。

typings.d.ts

declare module "*.json" {
   const value: any;
   export default value;
}

comp.ts

import * as data from './data.json';

【讨论】:

  • 伙计,我非常感谢您的帮助,但不幸的是,修改 typings.d.ts 文件对我来说也不是一个选项,正如我在原始帖子中所解释的那样。
【解决方案2】:

我找到的解决方案是使用 RequireJS,我可以通过 Angular CLI 框架使用它。

我必须将 require 声明为全局变量:

declare var require: any;

然后我可以使用require.context 来获取我创建的文件夹中的所有文件,以保存../types 的类型。

请在下面找到完整的服务,该服务将所有 JSON 文件(每个文件都是一个类型)加载到服务变量 types

结果是一个类型的对象,其中类型的键是文件名,相关的值是文件中的 JSON。

从文件夹../types 加载文件type1.jsontype2.jsontype3.json 的示例结果:

{
    type1: {
        class: "myClass1",
        property1: "myProperty1"
    },
    type2: {
        class: "myClass2",
        property1: "myProperty2"
    },
    type3: {
        class: "myClass3",
        property1: "myProperty3"
    }
}

最终服务文件

import { Injectable } from '@angular/core';

declare var require: any;

@Injectable()
export class TypeService {

    constructor(){
        this.init()
    };

    types: any;

    init: Function = () => {

        // Get all of the types of branding available in the types folder
        this.types = (context => {

            // Get the keys from the context returned by require
            let keys = context.keys();

            // Get the values from the context using the keys
            let values = keys.map(context);

            // Reduce the keys array to create the types object
            return keys.reduce(
                (types, key, i) => {

                    // Update the key name by removing "./" from the begining and ".json" from the end.
                    key = key.replace(/^\.\/([^\.]+)\.json/, (a, b)=> { return b; });

                    // Set the object to the types array using the new key and the value at the current index
                    types[key] = values[i].data; 

                    // Return the new types array
                    return types; 
                }, {}
            );
        })(require.context('../types', true, /.json/));
    }
}

【讨论】:

    【解决方案3】:

    您可以从构造函数中定义的对象直接访问服务中的变量。

    ...所以说你的构造函数像这样加载服务

    constructor(private someService:SomeService){}
    

    您可以通过someService.theJsonObject 访问它。

    请注意在它被加载它的服务函数加载之前不要这样做。然后你会得到一个空值。


    您可以像在组件文件中一样将变量分配给服务文件。

    只需在服务中声明它们

    public JsonObject:any;
    

    并且(最简单的方法)是让调用您的服务的函数为您分配 JSON 对象。

    假设你这样调用服务

    this.serviceObject.function().subscribe
    (
      resp =>
      {
        this.serviceObject.JsonObject = resp;
      }
    );
    

    完成一次后,其他组件可以使用someService.theJsonObject 访问该 JSON 内容,如前所述。


    在您的情况下,我认为您需要做的就是将您的 JSON 对象嵌入到您的代码中。也许你可以使用const。这不是坏代码或任何东西。

    【讨论】:

    • 我相信 OP 希望直接从服务中访问本地 JSON 文件,然后将该数据分配给变量。
    • 问题在于如何将 JSON 分配给服务中的变量,而不是在从另一个组件在服务中分配它们后如何访问它们。
    猜你喜欢
    • 2012-06-11
    • 2011-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    相关资源
    最近更新 更多