Omar
Omar

Reputation: 8145

Get OData $metadata in JSON format

is it possible to get metadata of an OData service in JSON format?

When I try to use format=json , it doesn't work. Here is what I tried:

http://odata.informea.org/services/odata.svc/$metadata/?format=json

Upvotes: 23

Views: 56612

Answers (6)

mounds
mounds

Reputation: 1383

In 2021, possibly...

The OData 4.01 specification includes support for JSON: https://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part1-protocol.html#sec_MetadataDocumentRequest

Microsoft's OData implementation added support from the following versions:

  • ODataLib 7.7.3 (released 24 Sep 2020)
  • WebAPI 7.5.4 (released 29 Dec 2020)

Additionally, JSON Metadata is only supported at platform implementing .NETStardard 2.0. [sic].

If the service you're calling supports it, you can do it in the query string...

  • $format=application/json
  • $format=json

...or using the http headers:

  • Accept=application/json

It it doesn't... ask the provider of the service to upgrade?

Upvotes: 0

johnny 5
johnny 5

Reputation: 20997

I wrote a simple provider to parse out some of the needed information from the metadata, Feel free to expand on it. First you'll need some simple models, to expresss the data, we'll want to convert from there ugly XML names

export class ODataEntityType
{
    name: string;
    properties: ODataProperty[];
}

export class ODataProperty
{
    name: string;
    type: ODataTypes;
    isNullable: boolean;
}

//Hack Until Ionic supports TS 2.4
export class ODataTypeMap
{
    "Edm.Int32" = ODataTypes.Int;
    "Edm.Int64" = ODataTypes.Long;
    "Edm.Decimal" = ODataTypes.Decimal;
    "Edm.Double" = ODataTypes.Double;
    "Edm.Guid" = ODataTypes.Guid;
    "Edm.String" = ODataTypes.String;
    "Edm.Boolean" = ODataTypes.Bool;
    "Edm.DateTime" = ODataTypes.DateTime;
    "Edm.DateTimeOffset" = ODataTypes.DateTimeOffset;
}

export enum ODataTypes
{
    Int,
    Long,
    Decimal,
    Double,
    Guid,
    String,
    Bool,
    DateTime,
    DateTimeOffset
}

This is the provider:

import { Injectable } from "@angular/core";
import { Http } from "@angular/http";
import * as X2JS from 'x2js';
import * as _ from 'underscore';
import { ODataEntityType, ODataProperty, ODataTypes, ODataTypeMap } from "../models/ODataEntityType";

@Injectable()
export class ODataMetadataToJsonProvider  {

    x2js = new X2JS();

    public entityTypeMap: Dictionary = new Dictionary();

    public entityTypes : ODataEntityType[];

    constructor(public http: Http) {
    }

    parseODataMetadata(metadataUrl: string) {
        this.http.get(metadataUrl).subscribe(data => {
            let metadata: any = this.x2js.xml2js(data.text());

            let rawEntityTypes = _.filter(metadata.Edmx.DataServices.Schema, x => x["EntityType"] != null);

            if(rawEntityTypes.length == 0)
            {
            return;
            }

            this.entityTypes =  _.map(rawEntityTypes[0]["EntityType"], t => { 
                let oDataEntityType = new ODataEntityType();
                oDataEntityType.name = t["_Name"];
                oDataEntityType.properties = _.map(t["Property"], p => {
                    let property = new ODataProperty();
                    property.name = p["_Name"];
                    let typeStr: string = p["_Type"];
                    property.type = ODataTypeMap[typeStr];
                    property.isNullable = !!p["_Nullable"];
                    return property;
                });

                return oDataEntityType;
            });
        });
    }
}

Upvotes: 1

Michael Sebastian
Michael Sebastian

Reputation: 329

You can use jQuery to get the relevant information from an OData service $metadata.

Take for example:
You write a unit test to check the OData entities property names matches with your application entities. Then you have to retrieve the properties of the OData entity.

$.ajax({
            type: "GET",
            url: "/destinations/odata-service/$metadata",
            beforeSend: function() {
                console.log("before send check");
            },
            dataType: "xml",
            contentType: "application/atom+xml",
            context: document.body,
            success: function(xml) {
                console.log("Success ResourceTypes");   
                var ODataTypeINeed = $(xml).find('EntityType').filter(function(){ 
                                         return $(this).attr('Name') == 'ODataTypeINeed'
                                    });                 
                $(ODataTypeINeed).find('Property').each(function() {
                    console.log($(this).attr('Name')); //List of OData Entity properties
                });
            },
            error: function(err) {
                console.log(err);
            }
 });

Upvotes: 1

John Slegers
John Slegers

Reputation: 47091

As an alternative to ?$format=json, you could also just set the following two headers :

  • Accept: application/json
  • Content-Type: application/json; charset=utf-8

I'm not sure which is the minimum Odata version required, but this works perfectly for me on Microsoft Dynamics NAV 2016, which uses Odata v4.

Upvotes: 2

Jen S
Jen S

Reputation: 4555

The $metadata document is in the CSDL format, which currently only has an XML representation. (As a side note, if you do want to request the json format for a different kind of OData payload, make sure the format query token has a $ in front of it: $format=json.)

So, no it is not possible. You can, however, get the service document in JSON, which is a subset of the $metadata document:

http://odata.informea.org/services/odata.svc?$format=json

This won't have type information, but it will list the available entry points of the service (i.e., the entity sets).

Upvotes: 29

Thierry Templier
Thierry Templier

Reputation: 202176

I agreed with the previous answer. This isn't supported by the specification but some OData frameworks / libraries are about to implement this feature.

I think about Olingo. This is could be helpful for you if you also implement the server side. See this issue in the Olingo JIRA for more details:

Hope it helps you, Thierry

Upvotes: 1

Related Questions