在没有HTTP请求的情况下加载JSON

时间:2017-06-01 16:45:32

标签: json angular angular2-services

我正在使用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

我需要使用my.service.ts的{​​{1}}服务来加载JSON文件@Injectable。对于我的特定情况,将在myJson.json文件旁边放置多个JSON文件,这些文件都需要加载。

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

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

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

摘录:

my.service.ts

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

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

摘录:

解决方案:使用通配符模块名称 在TypeScript版本2 +中,我们可以在模块名称中使用通配符。在您的TS定义文件中,例如// 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

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

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

问题

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

3 个答案:

答案 0 :(得分:4)

如果直接调用json,将会出现错误,但一个简单的解决方法是为所有json文件声明打字。

typings.d.ts

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

comp.ts

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

答案 1 :(得分:2)

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

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

declare var require: any;

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

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

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

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

{
    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/));
    }
}

答案 2 :(得分:-1)

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

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

constructor(private someService:SomeService){}

您只需someService.theJsonObject即可访问它。

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

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

只需在服务中声明它们

即可
public JsonObject:any;

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

所以说你打电话给这样的服务

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

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

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