Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert Complex Object to Query String

How can I convert complex Object to a Query String intended for 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>();
}

I'm trying to write a generic function to convert a complex type to basic query I wrote this function to convert a simple object to query string

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;
    }
}

But I'm having trouble grasping how I can do this recursively for complex object with enums and arrays etc? Can anyone point me in the right direction or to something build in that already does this?

like image 424
johnny 5 Avatar asked Jul 26 '26 05:07

johnny 5


1 Answers

Incase anyone was wondering how to do this, I've written an extension that should work with c# .Net Core 1.1 and Typescript 2.2.2 WebApi which looks like so.

Remember to include these two imports where you are using it as well

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());
        }
    }
}

This is working for all the complex types I've used so far.

EDIT Usage I've included all of the import statements I believe the important ones are RequestOptionsArgs, RequestOptions, but I remembered their required so just incase I've included them all.

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());
    }
 }
like image 59
johnny 5 Avatar answered Jul 27 '26 20:07

johnny 5



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!