将复杂对象转换为查询字符串

时间:2017-08-10 02:56:31

标签: angular typescript generics

如何将复杂对象转换为用于WebApi的查询字符串:

export enum FilterCondition {
    Equal,
    NotEqual,
    GreaterThan,
    LessThan,
    GreaterThanEqual,
    LessThanEqual
}

export class QueryParameter {
    propertyName: string;
    filterCondition: FilterCondition
    value: string;
}

export class QueryOptions {
    queryParameters: QueryParameter[] = new Array<QueryParameter>();
}

我正在尝试编写一个通用函数来将复杂类型转换为基本查询 我写了这个函数来将一个简单的对象转换为查询字符串

export class QueryStringBuilder {
    static BuildParametersFromSearch<T>(obj: T): URLSearchParams {
        let params: URLSearchParams = new URLSearchParams();

        const objectKeys = Object.keys(obj) as Array<keyof T>;
        for (let key of objectKeys) {
            params.set(key, obj[key])
        }

        return params;
    }
}

但是我无法掌握如何使用枚举和数组等递归复制对象?任何人都可以指出我正确的方向或已建立的东西吗?

1 个答案:

答案 0 :(得分:3)

如果有人想知道如何做到这一点,我写了一个扩展应该与c#.Net Core 1.1和Typescript 2.2.2 WebApi一起工作。

请记住在您使用它的地方也包含这两个导入

import { URLSearchParams } from '@angular/http';
import 'rxjs/add/operator/map'

export class QueryStringBuilder {
    static BuildParametersFromSearch<T>(obj: T): URLSearchParams {
        let params: URLSearchParams = new URLSearchParams();

        if (obj == null)
        {
            return params;
        }

        QueryStringBuilder.PopulateSearchParams(params, '', obj);

        return params;
    }

    private static PopulateArray<T>(params: URLSearchParams, prefix: string, val: Array<T>) {
        for (let index in val) {
            let key = prefix + '[' + index + ']';
            let value: any = val[index];
            QueryStringBuilder.PopulateSearchParams(params, key, value);
        }
    }

    private static PopulateObject<T>(params: URLSearchParams, prefix: string, val: T) {
        const objectKeys = Object.keys(val) as Array<keyof T>;

        if (prefix) {
            prefix = prefix + '.';
        }

        for (let objKey of objectKeys) {

            let value = val[objKey];
            let key = prefix + objKey;

            QueryStringBuilder.PopulateSearchParams(params, key, value);
        }
    }

    private static PopulateSearchParams<T>(params: URLSearchParams, key: string, value: any) {
        if (value instanceof Array) {
            QueryStringBuilder.PopulateArray(params, key, value);
        }
        else if (value instanceof Date) {
            params.set(key, value.toISOString());
        }
        else if (value instanceof Object) {
            QueryStringBuilder.PopulateObject(params, key, value);
        }
        else {
            params.set(key, value.toString());
        }
    }
}

这适用于我目前使用的所有复杂类型。

编辑用法我已经包含了所有的导入语句,我认为重要的是RequestOptionsArgs,RequestOptions,但我记得他们的必需,所以只是因为我把它们都包括在内。

import { Injectable } from '@angular/core';
import { Http, Headers, RequestOptionsArgs, RequestOptions } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { IHasId } from '../interfaces/interfaces';
import 'rxjs/add/operator/map';

import { QueryOptions, IFilterNode } from "../models/queryOptions";
import { QueryStringBuilder } from "../models/QueryStringBuilder";

import 'rxjs/add/operator/map'

@Injectable()
export class ProviderBase<T extends IHasId> {

    getList(filterParams?: IFilterNode): Observable<T[]> {
        var searchParams = QueryStringBuilder.BuildParametersFromSearch(filterParams);

        let requestArguments: RequestOptionsArgs = new RequestOptions({ search: searchParams });
        return this.http.get(`${this.apiUrl}/${this.route}`, requestArguments).map(res => <T[]>res.json());
    }
 }