Note that this question is at the border of StackOverflow and ProWebmasters, so please forgive me if you think that it belongs to SO; but I'm afraid that it would be closed over there as "not a programming question". Anyway:

I'm implementing a PHP library to parse schema.org structured data and represent them using objects that match schema.org types: Product, Offer, etc.

I've so far identified 3 ways properties are used:

  • The property has a Thing type, and is marked up as such

    Example: Product.offers

    This is self-explanatory, and can be translated in code as a $offers property containing a list of Offer objects:

    "@type": "Product",
    "offers": {
        "@type": "Offer",
        "availability": "http://schema.org/InStock",
        "price": "55.00",
        "priceCurrency": "USD"

    This maps straight to code that could look like:

    class Product {
        /** @var Offer[] */
        public $offers;

  • The property has a Text type, and is marked up using a simple string

    Example: Product.color

    This is self-explanatory as well: Text is a DataType. It can be mapped in code to a native data type such as string:

    "@type": "Product",
    "color": "red",
    class Product {
        /** @var string */
        public $color;

    The same goes with properties of type Number, Date, etc. These are all DataTypes that could map to a native type in code, and that make sense to mark up as a simple string.

  • The property has a Thing type, but the docs suggest to use it as a text property (!)

    Example: ExerciseAction.distance

    Distance is not a DataType, it's an object that extends from Thing and whose only properties are those inherited from Thing:

    Thing > Intangible > Quantity > Distance

    Still, the doc does not say to mark it up as an object with properties, but as a simple text string. Example straight from ExerciseAction:

    "@type": "ExerciseAction",
    "distance": "100 miles",

I'm struggling with this last one, which seems to be a mix of a Thing and a DataType.

Question 1

How am I supposed to represent a Distance in code, when it's represented as text in the markup?

As a Distance is a Thing, it would feel wrong to me to represent it as a string in code; I'd rather convert this text value to a Distance object. But then, where should the textual value go? In the name property for example?

Is handling of these Quantity values documented anywhere? I found an issue on the schemaorg repo that seems to support the feeling that there's an ambiguity here.

Question 2

Is a text string the only correct usage for a Distance property, or can we encounter a Distance as an object, such as the following?

"@type": "ExerciseAction",
"distance": {
    "@type": "Distance",
    "name": ...

Note that Google's structured data testing tool does not seem to care and accepts both. It does not seem to apply any conversion either, i.e. it outputs a textual distance as is, without converting it to a @type Distance.

I've browsed for other implementations of schema.org parsers to get inspiration (and answers) from, in any language, but didn't find anything close to what I'm trying to achieve here.

  • Just in case you missed it: properties can also have a URL value. While this is also a DataType, you can’t treat it as regular string, because the URLs might be relative references.
    – unor
    Commented Jun 4, 2019 at 5:00
  • Can all properties have a URL value? Why do some of them explicitly have URL in their type list, and others do not? Could you please point me to the relevant docs? Thank you!
    – BenMorel
    Commented Jun 4, 2019 at 7:38
  • 1
    Yes, all properties can have a URL value (see Conformance). It’s explicitly listed for those properties for which it’s common/useful/making sense to provide URLs.
    – unor
    Commented Jun 4, 2019 at 10:59

1 Answer 1


The property distance can be extended with type Distance. In turn, this type has the property identifier that can be extended using the type PropertyValue. This type has the following properties that may be useful to you:

  • value
  • unitText
  • unitCode

All of the above creates data type embedding. So my suggestion is how to present your 100 miles as a distance with the specified unit length:

  "distance": {
  "participant": {
    "@type": "Person",
    "name": "Steve"

Note that the property sameAs has value as the link of Units of Measure: Code elements listed by name.

  • I don’t think it makes sense to use identifier and sameAs like that. a) "100 miles" is not the identifier of the Distance item. b) The sameAs for the PropertyValue item would have to be a URI that represents this specific property value (i.e., 100 miles, and probably exactly these specific 100 miles, not just any).
    – unor
    Commented Jun 4, 2019 at 4:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.