odataodata-v4

Odata v4 - $expand then flattern result


Objective: To expand an object, and project a nested property, onto the root selection, alongside with other props.

Having the following relationship:

public class Product {
   public string Barcode { get; set; }
   public double Price { get; set; }
   public Category Category { get; set; }
}

public class Category {
   public string Name { get; set; }
}

I would like to make a projection which will result in this:

{
   "@odata.context": "http://localhost/odata/$metadata#Product",
   "value": [
      {
         "Price": 500,
         "Name": "Meat Products" // this is category name, ideally would be to rename it to CategoryName
      }
   ]
}

Where as currently I get this:

{
   "@odata.context": "http://localhost/odata/$metadata#Product",
   "value": [
      {
         "Price": 500,
         "Category": {
            "Name": "Meat Products"
         }
      }
   ]
}

The query used is the following:

/odata/Product?$expand=Category($select=Name)&$select=Price

I would expect to write a projection like this:

/odata/Product?$expand=Category&$select=Price,Category/Name as CategoryName

or

/odata/Product?$expand=Category&$select=Price,Category($select=Name as CategoryName)

or

/odata/Product?$expand=Category&$select=Price,Category($select=Name)

Is that achievable ? Thank you!

P.S. OData V4.


Solution

  • This is not achievable with odata v4 query semantic. As you can see, the response body contains a line:

    "@odata.context": "http://localhost/odata/$metadata#Product"
    

    This is to indicate the whole response payload represents an instance of 'Product' type. Suppose 'CategoryName' property does not exist on that type, it is not possible to instruct service to dynamically add one via the 'AS' clause. And keyword 'AS' also does not exist in standard OData query spec.

    However, it is indeed valid to return an additional property beyond the metadata, see Reference.

    Clients MUST be prepared to receive additional properties in an entity or complex type instance that are not advertised in metadata, even for types not marked as open.

    So in this case, the service could just return an additional 'virtual' property 'CategoryName' in the response. (If you're the service owner you can update response logic and do the change.) This could be a service behavior, rather than a reaction to certain client query.