Trait concepts and use cases
Traits are the fundamental mechanism in the Common Data Model metadata grammar for describing the data format, semantic meaning, and specifications for entities, attributes and other objects, such as partitions or manifests. This article explains the following concepts and use cases of Common Data Model traits.
- How Common Data Model standard traits are described
- How Common Data Model standard traits represent the format of stored data values
- Translation using the Common Data Model SDK
- Equivalence of traits when converting to or from the previous representation of Common Data Model folders (referred to as the model.json file format)
For reference, the current form for representing Common Data Model metadata is called the manifest format. The Common Data Model manifest format encompasses several critical enhancements over the more limited model.json format. For more information, see Common Data Model manifest object.
For detailed information about the model.json document format, see Metadata file for the Common Data Model.
What are traits?
Traits are annotation objects that are an expression of semantic meaning. Traits can hold a set of named argument values. When an entity is in the resolved form, that is, when it is being used to map out the specific layout of data records, an entity object can be as little as a named collection of references to traits, along with a list of attributes where each attribute is simply a named collection of references to traits.
For example:
{
"definitions":[
{
"entityName":"Device",
"displayName":"Device",
"description":"A device that is an application or browser instance",
"version":"0.9",
"hasAttributes":[
{
"name":"manufacturer",
"appliedTraits":[
"is.dataFormat.character",
"is.dataFormat.array"
],
"displayName":"Manufacturer",
"description":"The name of the organization who owns the design and creation…",
"dataFormat":"String"
}
]
}
]
}
Notice that there are some properties on the entity and attributes that do not look like trait references. However, the helper properties such as displayName, description and dataFormat, are representing hidden trait values. These traits still exist in the Common Data Model object model and can be accessed as traits instead of property values.
A string such as "means.measurement.distance.pixels" are referred to as trait references because each of them corresponds to a trait object that is defined (perhaps in another document) in the Common Data Model system. Using the Common Data Model object model, these strings are actually TraitReference objects that can be queried to fetch the underlying TraitDefinition.
The example below (using the code example above) shows what trait definitions look like in a Common Data Model definition document.
Note in this example:
By convention, trait names describe the meaning and domain of the trait by using a word.word.word format. As part of the convention, the first word is either a namespace identifier (for custom extensions) or the verb "is", "does", "has" or "means".
A best practice is to give traits an explanation that makes it clear when or where the traits should be applied.
Traits can be defined as extensions of a base trait. This creates an inheritance hierarchy that allows for mixing specific and general expressions of meaning. For example, if means.measurement.distance extends means.measurement, and means.measurement.temperature also extends means.measurement, then any object that exhibits either of the more specific traits for distance or temperature can also be seen to have the means.measurement trait. This is useful for searching or grouping.
Traits can define a set of named parameters that give additional details about the trait or a setting.
Trait parameters have the following qualities:
- a name and explanation
- can be required or optional
- can have default values
- have an expected data type
The dataType for a trait parameter can be any of the data types defined in the Common Data Model system.
In this example, because the base trait parameter for "units"' is set to "Meters", when any other object has this means.measurement.distance.meters trait applied to it, the units argument will always be "Meters".
A defined trait, such as means.measurement, can then be applied or used by making a reference to the defined trait.
An example of a simple trait reference is the use of means.measurement as the base or "extendedTrait" for the means.measurement.distance trait.
A structured reference to a trait, as in the object shown which describes the base trait for means.measurement.distance.meters, allows for the setting of trait arguments for that specific use of the trait.
The supplied trait arguments correspond to the defined trait parameters, including the trait parameters that may be inherited from a base trait.
A trait argument can be a simple string value. This assumes that values are set on parameters in the order the values are defined, starting from the deepest base trait on up.
Another way to specify trait arguments is with name and value pairs in an object.
Trait arguments for simple values are always expressed as strings, even if the trait parameter has a dataType such as integer or boolean.
Trait argument values for complex types, such as attributes or entities, can be objects.
Maintaining a standard naming convention simplifies collections of traits into understandable and standard semantic groups. Standard semantics include:
Trait base collection Description Example is The actual value, format or shape of the data object or attribute. The is.dataFormat.array attribute is a string with an array of characters. does How the data object or attribute affects or contributes to another attribute. The does.haveDefault attribute indicates if a default value is required, present or applied. has Describes the characteristic or shape of an attribute. The has.format("L, F M") attribute specifies the acceptable data format, in this case Lastname , Firstname Middlename. means What the data object or attribute relates to or represents. The means.location.city attribute is the location having a city name.
Trait specifics
Property / Method | Description |
---|---|
traitName | The name of the trait. |
extendsTrait | A trait reference to a trait of which this trait extends. This trait will inherit all parameters from the base trait. |
parameters | A list of parameters (see below) for holding values or settings with the trait. |
elevated | Beyond the scope of this document. |
Trait parameters
Property / Method | Description |
---|---|
name | A unique name for the parameter. This name can be used to set argument values when referencing traits. |
defaultValue | A default value for the parameter that is used if no corresponding arguments are set. |
dataTypeRef | A Common Data Model dataType that describes the meaning and shape of the values that can be represented by this parameter. |
required | If True, the object model will report an error if a trait is referenced and no value has been set as an argument for this trait. |
Ascribing traits (overriding exhibited trait behavior)
Traits can be part of the definition of an object or can be attached to a particular reference to an object.
When an entity or other object is defined in Common Data Model, part of its definition can be the set of traits that the object will exhibit. This means that any time the object is used by reference, it will have those traits.
In attribute definitions and in the places where a Common Data Model object is used by reference, additional traits may be applied. These additional traits will sit along with the object's exhibited traits. Applying a trait on an object reference overrides the parameter values of the identically named trait that is exhibited by the object.
Trait data types and data format
Common Data Model traits have dataTypes, a dataFormat property, and a relationship to the older model.json dataType enumeration.
There are a set of Common Data Model traits that express aspects of the format of a data value in a storage-agnostic way.
Trait Name | Description |
---|---|
is.dataFormat.integer | A whole number |
is.dataFormat.floatingPoint | An approximation of a number with optional whole, fractional and power of 10 parts |
is.dataFormat.character | An encoded text character |
is.dataFormat.byte | A byte of data |
is.dataFormat.boolean | True or False |
is.dataFormat.numeric | A fixed precision floating point number that may have precision and scale |
is.dataFormat.time | A representation of a time of day |
is.dataFormat.date | A representation of a calendar date |
is.dataFormat.timeOffset | A representation of a timezone offset |
is.dataFormat.guid | A representation of a 128 bit globally unique identifier |
is.dataFormat.big | A modifier, indicates the doubled size of some numeric values |
is.dataFormat.small | A modifier, indicates the half size of some numeric values |
is.dataFormat.array | A modifier, the base format is repeated sequentially |
dataType
A Common Data Model dataType is an object that represents a collection of traits. All dataTypes should indicate the dataFormat traits but can also add additional semantic information.
The primitive dataTypes in Common Data Model are:
dataType name | Traits |
---|---|
integer | is.dataFormat.integer |
float | is.dataFormat.floatingPoint |
decimal | is.dataFormat.numeric.shaped (extends is.dataFormat.numeric) |
boolean | is.dataFormat.boolean |
byte | is.dataFormat.byte |
binary | is.dataFormat.byte, is.dataFormat.array |
char | is.dataFormat.character, is.dataFormat.array |
string | is.dataFormat.character, is.dataFormat.array |
smallInteger : extends 'integer' | is.dataFormat.integer, is.dataFormat.small |
bigInteger : extends 'integer' | is.dataFormat.integer, is.dataFormat.big |
double : extends 'float' | is.dataFormat.float, is.dataFormat.big |
guid : extends 'string' | is.dataFormat.guid, is.dataFormat.character, is.dataFormat.array |
date | is.dataFormat.date |
time | is.dataFormat.time |
dateTime | is.dataFormat.date, is.dataFormat.time |
dateTimeOffset :extends 'dateTime' | is.dataFormat.date, is.dataFormat.time, is.dataFormat.timeOffset |
An example of a more meaningful dataType is "city", which extends "string" and adds the means.location.city trait.
dataFormat
Since dealing with the set of is.dataFormat traits that might originate from various semantic dataTypes can be awkward, the Common Data Model system converts these traits into a first class property on the Attribute object called the dataFormat. The dataFormat is computed from the traits found on the attribute. dataFormat values correlate with the intrinsic dataTypes listed above.
The best practice is to use a semantically rich dataType in your entity definition. However, it is possible to explicitly set the dataFormat property to one of the enumeration values; doing so will add the associated traits to the attribute.
dataFormat | Traits |
---|---|
Unknown | No combination of traits could be recognized |
Int16 | is.dataFormat.integer, is.dataFormat.small |
Int32 | is.dataFormat.integer |
Int64 | is.dataFormat.integer, is.dataFormat.big |
Float | is.dataFormat.float |
Double | is.dataFormat.float, is.dataFormat.big |
Guid | is.dataFormat.character, is.dataFormat.array, is.dataFormat.guid |
String | is.dataFormat.character, is.dataFormat.array |
Char | is.dataFormat.character |
Byte | is.dataFormat.byte |
Binary | is.dataFormat.byte, is.dataFormat.array |
Time | is.dataFormat.time |
Date | is.dataFormat.date |
DateTime | is.dataFormat.date, is.dataFormat.time |
DateTimeOffset | is.dataFormat.date, is.dataFormat.time, is.dataFormat.timeOffset |
Boolean | is.dataFormat.boolean |
Numeric | is.dataFormat.numeric |
Decimal | is.dataFormat.numeric.shaped (extends is.dataFormat.numeric) |
Json | is.dataFormat.character, is.dataFormat.array, means.content.text.JSON |
model.json types
When converting to and from the model.json persistence format for a Common Data Model entity, the following conversion takes place:
Source dataFormat | model.json dataType | Destination dataFormat |
---|---|---|
Unknown | unclassified | Unknown |
Byte | unclassified | Unknown |
Binary | unclassified | Unknown |
Int16 | int64 | Int64 |
Int32 | int64 | Int64 |
Int64 | int64 | Int64 |
Float | double | Double |
Double | double | Double |
Guid | guid | Guid |
String | string | String |
Char | string | String |
Time | time | Time |
Date | date | Date |
DateTime | dateTime | DateTime |
DateTimeOffset | dateTimeOffset | DateTimeOffset |
Boolean | boolean | Boolean |
Decimal | decimal | Decimal |
Json | json | Json |
Standard Traits
The standard definition documents for Common Data Model are primitives.cdm.json, foundations.cdm.json, and meanings.cdm.json (located at https://github.com/microsoft/CDM/tree/master/schemaDocuments). These standard definition documents contain a number of pre-defined standard traits that should be used or extended to help create a shared understanding of metadata from different systems. These standard traits define data formats, data shapes, usage guidance and restrictions, semantic meanings, and structural information about the relationships within the entity itself.
For more explanation, consider the following examples:
Trait name | Description |
---|---|
is.dataFormat.integer | Part of the dataFormat set of traits, indicates that the attribute represents whole numbers. |
means.identity.entityId | Set for an attribute that holds an identifier (primary key) value for an entity |
is.required | Specifies that an attribute is required |
is.CDM.entityVersion | Holds the version number for the schema of an Entity |
is.localized.displayedAs | The "Display Name" for an attribute or entity. Holds a table of language specifics strings. |
is.correlatedWith | Indicates that the values found in the tagged attribute are correlated with the values from another indicated attribute. |
means.calendar.dayOfWeek | Part of the Calendar trait set. Indicates the day of the week. Note that the data values could be "Mon, Tues" or 0,1,2, and this trait is still valid. Another trait like dataFormat.integer indicates the data shape. |
means.demographic.maritalStatus | Marital status. Such an attribute can also, with other traits, be constrained to a specific list or an enum of possible values. |
means.formatting.font.size | Could be used in an application to set a standard font size |
means.idea.product | Could be used on an entity that holds product information. |
means.location.city | Contains the name of a city. |
means.measurement.distance.inches | Inches. Also defines measurement and measurement of distance. |
means.identity.person.fullName | The full name of a person. |
The full set of standard traits can be broken down into the following groups/documents. Note that all of the standard "meanings" documents hold semantic traits and dataTypes.
Document/Group | Description |
---|---|
primitives.cdm.json | Fundamental traits used by the Common Data Model system internally. Basic building blocks of data formats. |
foundations.cdm.json | Key concepts that Common Data Model entities use to express ideas such as "localized display names", and "enumerations of values". |
structural | is.hidden, is.ordered, means.content.text.XML |
Meanings Concepts (meanings.concepts.cdm.json) |
Business concepts and objects: means.idea.product,* means.idea.schedule*, means.category, means.relationship |
Meanings Identity (meanings.identity.cdm.json) |
Semantics about identifying things and people: means.identity.barCode, means.identity.person.fullName, means.identity.tickerSymbol |
Meanings Calendar (meanings.calendar.cdm.json) |
Describing the parts of fiscal and other calendars: means.calendar.day, means.calendar.weekOfYear, means.calendar.ISO8601 |
Meanings Measurement (meanings.measurement.cdm.json) |
Measurement of physical and other dimensions: means.measurement.density, means.measurement.sequence, means.measurement.currency.revenue, means.measurement.duration.hours |
Meanings Formats (meanings.formats.cdm.json) |
Color, font, ordering. |
Meanings Demographics (meanings.demographics.cdm.json) |
Age, gender, income level: means.demographics.birthDate |
Meanings Location (meanings.location.cdm.json) |
Address and locations: means.location.address.street, means.location.latitude, means.location.geo.boundary.left |
Meanings Privacy (meanings.privacy.cdm.json) |
Data Subject actions, Identifiability, category, usage and consent requirements: privacy.dataCategory.endUser.feedback, privacy.dataUsage.research, privacy.consent.optIn |
Traits in the Common Data Model object model
When working with objects such as entities, attributes, partitions, the Common Data Model object model largely follows the concepts one sees in the persisted JSON documents. The objects have a property of type CdmCollection<CdmTraitReference>
, called "appliedTraits" or "exhibitedTraits", that contains a set of trait references. A trait reference can be queried for the definition object (fetchObjectDefintion) if needed. Each trait reference can contain a collection of arguments. These are the arguments that supply values to any defined trait parameters. An API call using "FetchFinalTraitArguments" will return a map from argument names to the final values of each parameter, when considering the inheritance hierarchy of the trait, any default values for parameters, and any argument values that have been set along the way.
Consult the Common Data Model object model documentation and sample code projects for details on how to work with traits in code.
Traits in model.json
The model.json file format was the initial version of the format that describes Common Data Model folders. The Common Data Model manifest format is the new version that accommodates additional requirements and covers a superset of functionality of model.json. The Common Data Model SDK, available in multiple languages, provides automatic forward- (and backward-) translation between the metadata formats. The reference specification for manifest is publicly available at The Manifest object.
When the Common Data Model SDK is used to open a model.json document, the model.json document will be converted into a manifest object with references to EntityDefinitions. When a pbi:dataCategory custom extension is encountered on an entity or attribute, it will be automatically translated into the equivalent Common Data Model standard semantic trait and that trait will be attached to the converted Common Data Model entity or attribute.
Automatic translation to standard traits of specific PBI custom extensions
A set of PBI custom extensions will be translated into well-known traits. The best way to explain the correlation is to simply describe the traits:
{
"traitName": "is.extension.pbi:dataCategory",
"extendsTrait": "is.extension",
"explanation": "The Power BI data category for the entity or attribute this property is added for.",
"hasParameters": [
{
"name": "is.extension.pbi:dataCategory",
"dataType": "string",
"explanation": "Default parameter since extension isn't an object."
}
],
"traitName": "is.extension.pbi:mashup",
"explanation": "The mashup query and properties for the current document.",
"extendsTrait": "is.extension",
"hasParameters": [
{
"name": "fastCombine",
"dataType": "boolean",
"defaultValue": true,
"explanation": "The fastCombine for the mashup query."
},
{
"name": "allowNativeQueries",
"dataType": "boolean",
"defaultValue": false,
"explanation": "Set if native queries are allowed."
},
{
"name": "document",
"dataType": "string",
"explanation": "The mashup query for the current document."
},
{
"name": "queriesMetadata",
"dataType": "object",
"explanation": "Dictionary of query name to it's metadata containing query id, name, entity name etc."
}
],
"traitName": "is.extension.pbi:refreshPolicy",
"explanation": "The refresh policy for the entity. Full Refresh and Incremental Refresh are potential examples from Power BI.",
"extendsTrait": "is.extension",
"hasParameters": [
{
"name": "$type",
"explanation": "The type of the refresh policy.",
"dataType": "string"
},
{
"name": "location",
"explanation": "The root location to use for refresh.",
"dataType": "string"
},
{
"name": "rollingWindowGranularity",
"dataType": "string",
"explanation": "The granularity of the rolling window for the incremental refresh. it can be day, month, quarter or year.",
"defaultValue": "Invalid"
},
{
"name": "incrementalGranularity",
"dataType": "string",
"explanation": "The granularity of the incremental period in the window. it can be day, month, quarter or year.",
"defaultValue": "Invalid"
}
],
"traitName": "is.extension.pbi:partitionDataQuery",
"extendsTrait": "is.extension",
"explanation": "Stores the partition query.",
"hasParameters": [
{
"name": "is.extension.pbi:partitionDataQuery",
"dataType": "string"
}
],
"traitName": "is.extension.pbi:refreshBookmark",
"explanation": "The refresh bookmark for the last refresh of the partition.",
"extendsTrait": "is.extension",
"hasParameters": [
{
"name": "is.extension.pbi:refreshBookmark",
"dataType": "string"
}
],
"traitName": "is.extension.pbi:source",
"explanation": "The source for the partition.",
"extendsTrait": "is.extension",
"hasParameters": [
{
"name": "$type",
"explanation": "The type of source of the partition.",
"dataType": "string"
},
{
"name": "start",
"explanation": "The start date time for the ranged partition.",
"dataType": "string"
},
{
"name": "end",
"explanation": "The end date time for the ranged partition.",
"dataType": "string"
}
],
"traitName": "is.extension.pbi:timezone",
"explanation": "The timezone for which the times specified in the document are valid.",
"extendsTrait": "is.extension",
"hasParameters": [
{
"name": "is.extension.pbi:timezone",
"dataType": "string",
"default value": "Greenwich Mean Time"
}
]
}
Other custom extensions
Other custom extensions, "pbi" or other prefix, encountered in the model.json are turned into matching traits on the Common Data Model object.
The new trait extends from the is.extension trait.
The trait is named to match the custom extension.
If the custom extension has a value that is an intrinsic type, like 'string', then the trait is given one parameter having the same name as the trait and the intrinsic typed value is assigned to that parameter.
If the custom extension has a value that is a structured object, then the trait is given one parameter for each named member of the custom extension's object type.
As an example, consider the following custom extension.
{
"pbi:customThing": "valueFromModel"
}
The custom extension turns into the following trait definition.
{
"traitReference": "is.extension.pbi:customThing",
"arguments": [
{
"name": " is.extension.pbi:customThing",
"value": "valueFromModel"
}
]
}
Now, consider the following custom extension that has a value that is a structured object.
{
"pbi:customThing": {
"prop": "bet",
"sample": "valueFromModel"
}
}
The custom extension turns into the following trait definition that is given one parameter for each named member of the custom extension's object type.
{
"traitReference": "is.extension.pbi:customThing",
"arguments": [
{
"name": "prop",
"value": "bet"
},
{
"name": "sample",
"value": "valueFromModel"
}
]
}
Translation of annotations
Annotation in the model.json will also be turned into traits.
For example, the model.json form has the following annotation.
{
"annotations": [
{
"name": "pbi:EntityTypeDisplayHint",
"value": "LinkedEntity"
}
]
}
The Common Data Model object then exhibits this trait:
{
"exhibitsTraits": [
{
"traitReference": "is.modelConversion.otherAnnotations",
"arguments": [
{
"name": "annotations",
"value": [
{
"name": "pbi:EntityTypeDisplayHint",
"value": "LinkedEntity"
}
]
}
]
}
]
}
Note that saving a Common Data Model manifest as a model.json using the SDK will run these trait to extension conversions and trait to annotation conversions in reverse.
However, there will be Common Data Model traits that have no equivalent representation in the model.json form. These traits will show up as Common Data Model custom extensions. For example:
{
"attributes": [
{
"dataType": "dateTimeOffset",
"name": "createdOn",
"description": "Date and time when the record was created.",
"cdm:traits": [
"is.dataFormat.date",
"means.measurement.date",
"is.dataFormat.time",
"means.measurement.time",
"means.measurement.date.creation",
"is.CDS.standard",
{
"traitReference": "is.requiredAtLevel",
"arguments": [
"none"
]
}
]
}
]
}
This shows an attribute definition in a model.json that holds a cdm:traits custom extension with an array of the persisted trait references that one would also see in the equivalent EntityDefinition.