Hi @melissa7 this is a very interesting question. What’s going on here (unfortunately) has to do with some sanitization of how Bubble handles arrays. I’d never specifically come across this exact example (and it’s a good one), but to understand what’s going on:
[Correct me if I’m wrong on this first point…] The API connector returns to you a List of "Statics"
yes? And then, you are accessing a List of Static's data's ticker_symbol
(which resolves to a list of texts) and separately a List of _classes's data's cost_basis
(which resolves to a list of numbers). Anyway, it’s something like that, right? Or maybe it’s just a single object called “_class” or something.
And you are feeding those as inputs to two different Flow State Lists SSAs in the hopes that you now have two “parallel lists” – one of the ticker symbols and one of the corresponding cost bases. (You’re not being crazy to expect this, but that’s not how this works.)
However, sometimes you find there are a different number of elements in these two lists. (Missing values for the text list show as null and missing values for the numeric list are… well… just missing, right?)
I’ll explain why later, but in the meantime, here’s the tl;dr: DON’T SEND THOSE SUBLISTS TO MULTIPLE LIST POPPERS. Send the list of top-level objects to one List Popper. In your case the API Connector is sending you a list of "Static"s maybe or maybe it’s called a “_class”, I’m not sure. (Maybe it’s a list of "data"s? You could also send that.)
Anyway, when you do that, what List Popper returns to you is a SINGLE, SCALAR ITEM (it’s what we call an object in JavaScript, but Bubble calls it a “Thing”) held in the Popped Item output of List Popper. And, when you access the properties of that thing (List Popper’s Popped Item’s Some Property), you will get JUST THE VALUE FOR THAT INDIVIDUAL thing. In your case - when you do this right - that singular thing will have (for example), both a ticker symbol (singular) and a cost basis (singular) property. AND ONE OR THE OTHER OF THEM MAY BE EMPTY. But you will now know - “oh hey, this item has no ticker symbol” because List Popper's Popped Item's Ticker Symbol
or List Popper's Popped Item's Cost Basis
will be empty. And you can handle that as you see fit.
(I assume what you’re doing here is attempting to parse the API response into real Bubble objects and store them in the database… Since the API Connector’s version of the response is unusable in Bubble terms – I call these List type responses “API Ghetto” datatype.) Anyway, to make this work as expected, you send List Popper the list of objects that’s just above the individual items you are trying to parse. For example, if Blargs have a Foo and a Bar, send List Popper the list of Blargs and then as you iterate, you can inspect each Foo and each Bar, even if they are empty.
So here’s the “too long” part:
What’s going on does not relate to the code for FLOW State SSA nor to the code for List Popper SSA, unfortunately.
When, in Bubble, we look at an item that is a List and we then ask to give us the value of some property of the items in that list (by writing Some List of Things's Property
), we wind up with a Bubble List that is of some type.
And every individual Item in the List must be of the same, singular type. So – as in your example – the list might hold some texts or the list might hold some numbers, but there’s no such thing (generally) as a List in Bubble that contains BOTH some numeric values and some text values (for example).
This is not that case in JavaScript, where I can make an array that contains any sort of data types that I want. I can make an array that mixes different types of data (and those individual items might even be arrays or objects themselves!). For example, here’s an array that has both strings (what Bubble calls “texts”) and numbers in it:
var myarr = ["ABC", 1, 2, 3, "baby you and me, gurl"]
The first value is a string, the second thru fourth are numbers and the last one is a string.
Now, JavaScript arrays can also contain empty values, that are typically indicated by a special value called null
. And, in fact, in Bubble the concept of empty
is very similar to the concept of null
. I could go on a lot about this but it’s not entirely relevant to the conversation at hand.
Anyway, when you ask Bubble to take that list of (number type) Cost Bases into FLOW State SSA, the LOG MESSAGE you’re seeing (the one where you see numbers as well as nulls) isn’t what’s stored in FLOW State, it’s what’s going into FLOW State. And it’s a representation of the raw API response.
But THERE IS NO VALID REPRESENTATION of this JSON object in Bubble land. You could argue that there SHOULD be, but Bubble isn’t having it. That object gets converted into a proper Bubble list at the input of FLOW State. And, in a case like this (numeric list), it seems the nulls essentially get stripped out.
Inside of FLOW State (I’m talking about the actual code), we use a Bubble plugin API method (List.get()
)to fetch the contents of this List. And what we get back is just the numeric values… the nulls (somewhere in Bubble’s own code) get stripped out. Bubble doesn’t let numeric Lists contain anything but numbers and null
is not a number (it’s an object, actually).
Now, why is the handling different if the List is of type text? Well, there is such a thing as a null string and null does have a string representation, so it seems Bubble lists of text type allow nulls.
For example, if I have an array of strings and nulls like so:
var keith = ["one", "two", null, "three"]
This can be easily converted to a text representation of the entire array, by saying:
keith.toString()
which will yield the string:
'one,two,,three'
Or I could do something like, convert each individual element in the array to a string by:
keith.map(item => String(item))
which will give me an array of strings like so:
['one', 'two', 'null', 'three']
The above doesn’t really explain exactly why Bubble chooses to do this (and why it shows up in server-side plugins or in the API Connector, or whatever), but that’s just what it does.
I note that, if you create a very simple Server Side Action plugin with code as follows:
function(properties, context) {
var numlist = [1, 2, null, 4, 5, null, 7]
var stringlist = ["One", "Two", null, "Four", "Five", null, "Seven"]
return { "numeric_list": numlist, "string_list": stringlist }
}
The lists that come back into Bubble when this is executed abide by the same rules I described above: We get a list of 5 numbers and a list of seven “texts”, two of which are null:
Anyway, the results of your two list expressions cannot be guaranteed to have the same number of values, so what you do is send List Popper the list of objects you are interested in and then, in your iterative workflow, you examine the property values individually (by looking at the single, scalar Thing exposed by the Popped Item output of List Popper). Obvs, you then call the same workflow again, sending it the contents of the Remaining List output.