How to include nested properties is featuredProperties?

What’s up y’all?

I would love to include properties in featuredProperties which are nested within Objects.

In my case, I have a Schema of

{ properties: {market_data: {properties: price: {type: Number} } } }.

How am I able to to include ‘price’ in the featuredProperties of this Schema?

Thanks in advance,

Niklas

1 Like

Hi @Niklas_Benjamin_Muegge - Unfortunately the featuredProperties field currently only accepts the names of top-level properties, and there is no way to promote nested properties. The best workaround available at the moment is to change your schema to flatten out the set of properties, such that more are available at the top level. For example, create a market_price property instead of a nested market_data.price.

I think it would be nice if we supported nested properties in sync tables, and perhaps even other more complicated formulaic columns or even buttons. I’ll raise this with the team, but I wouldn’t expect to see a change here in the short term.

2 Likes

Hey @Eric_Koleda , thanks for your quick reply! What a bummer! That can get quite messy quite fast. I guess I’ll use two Schemas then - a flat one for the table and an hierarchical one for everything else. Enjoy your Friday and Stranger Things season 4 ~

1 Like

Hey @Eric_Koleda ~ since I am using a third party API, I cannot change the API format and thus flatten it. Do you know a way how would I be able to flatten the properties in this case?

Found it! I can simply make the formula return a flattened map :grin:

2 Likes

Excellent! I have noticed that folks sometimes have difficulty realizing that they can reshape the API data however they want before they return it, but you really are free to do anything! Wondering if there is a better place to introduce that concept or demonstrate it.

Great question! Well, I think, at least in my case, it isn’t an elegant solution and that might be the issue. I wanted the Schema to match the underlying API as closely as possible. But, to also have some properties available as ‘featuredProperties’, I had to duplicate the nested properties to be top-level, and thus having duplicate data. :grimacing: Yet, this, at least in my case, is the price to pay for the Schema being as close as possible to the underlying API.
I just created a pull request on GitHub that should resolve some of the uncertainty around this though :+1:

1 Like

Hi @Niklas_Benjamin_Muegge! Could you elaborate on how you returned a flattened map? I’m new to making Packs and am stuck on this part. @Eric_Koleda This might be a good question for you too!

Thank you both in advance!

Sure! So imagine your data comes back like this:

{
  "name": "Alice Smith",
  "address": {
    "street": "123 Apple ln.",
    "city": "Albany",
    "state": "New York",
  }
}

Suppose you want to show the person’s state as a featured property. You can’t do that directly, because you can specify a nested property in featuredProperties, only top-level properties. To work around this, first create a top-level property for the state and add it as a featured property:

let PersonSchema = coda.makeObjectSchema({
  properties: {
    name: {type: coda.ValueType.String},
    personId: {type: coda.ValueType.String},
    address: AddressSchema,
    state: {type: coda.ValueType.String}, // Adding this new property.
  },
  displayProperty: "name",
  idProperty: "personId",
  featuredProperties: ["state"],
});

Then in your execute function, after you get the JSON response back from the API, copy the state information up to the top-level object, so that it matches the schema.

let response = await context.fetcher.fetch(...);
let people = response.body;
for (let person of people) {
  // Pull up the state value.
  person.state = person.address.state;
}
return {
  result: people,
};

Your schema now includes the state information twice though, so an alternative approach is to copy up all the address fields to the top-level, and get ride of the address property altogether.

I hope this helps!

3 Likes

Thank you so much, @Eric_Koleda! This is incredibly helpful. :tada:

I’m trying these steps out right now but I’m getting a lot of errors, so I have a couple follow-up questions:

  • In the line inside PersonSchema that says address: AddressSchema, does this mean that I need to create an outside schema named AddressSchema as well?
  • The API I’m trying to work with has multiple levels of nested information in the JSON response. Does this same setup work for all the levels?

Yes, the pattern I recommend is defining a schema for each object, and nesting them as needed. You can see an example of that in the docs here.

let PersonSchema = coda.makeObjectSchema({
  properties: {
    name: { type: coda.ValueType.String },
    born: { type: coda.ValueType.String, codaType: coda.ValueHintType.Date },
    age: { type: coda.ValueType.Number },
  },
  // ...
});

let MovieSchema = coda.makeObjectSchema({
  properties: {
    title: { type: coda.ValueType.String },
    year: { type: coda.ValueType.Number },
    director: PersonSchema,
    actors: {
      type: coda.ValueType.Array,
      items: PersonSchema,
    },
  },
  // ...
});

Yes, you can keep nesting schemas within schemas within schemas.

1 Like

@Eric_Koleda It works!! :tada: Thank you so much for taking the time to answer my beginner questions and to point me in the right direction with the documentation!!

Sorry @Holly_Williams. Just now saw your message. Thanks @Eric_Koleda for the support. :pray:

This is a hugely helpful post, but I’m still struggling a little with how to construct the execute function. (I keep getting “not iterable” errors.) Is there any chance you could provide a “flattened map” example that includes both the schema declarations and then the execute functions, in order?

context: I am kind of learning JavaScript as I go here, so I am definitely in over my head…but I have got my first pack working other than the issue of pulling out the nested items, so it’s not hopeless!

Thanks in advance for any help you can provide.

UPDATE: It occurred to me to feed my code to GPT-4 to see if it could fix the problem, and it failed miserably…until I also gave it your advice from this post. It took some experimentation but eventually GPT helped me figure it out! So I’m all set. Also, GPT was useless without your wisdom!

1 Like