Locked learning resources

Join us and get access to thousands of tutorials and a community of expert JavaScript developers.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert JavaScript developers.

Unlock This Lesson

Turning Sets Into Arrays Before JSON

Turning Sets Into Arrays Before JSON

In this lesson, you added order 1042’s tags to the JavaScript label, found out why the Python script sorts them, and saw what JavaScript writes when you hand it a Set.

  • The Python script builds a set from the order’s tags, which drops the repeated "gift", and puts sorted(tags) in the label, not the set. That’s because json.dumps() would refuse the set, with TypeError: Object of type set is not JSON serializable, and because a Python set has no fixed order, so the same tags can come out either way round from one run to the next. Sorted, the tags come out in the same order every time.
  • Python’s sorted() ports as .toSorted(), but tags.toSorted() stops with TypeError: tags.toSorted is not a function. .toSorted() is an array method, and a Set isn’t an array.
  • A JavaScript Set keeps its items in the order they arrived, so the sort looks unneeded, and if JSON couldn’t take a Set, surely JavaScript would say so, as Python does. So it’s tempting to pass the Set itself. JSON.stringify() then writes "tags": {}, with no error, and the courier’s form would get no tags.
  • JSON has no set type. It knows six kinds of value: objects, arrays, strings, numbers, booleans (true and false), and null. JSON.stringify() treats a Set like any other object and writes out its properties, and a Set keeps its items inside, not as properties, so there’s nothing to write. A Map comes out empty the same way.
  • Python’s json.dumps() refuses a set, but JSON.stringify() writes a Set, or a Map, as an empty object, and says nothing.
  • The fix is to convert the Set to an array first: [...tags] spreads its items into a new array, like Python’s [*tags], and .toSorted() sorts it, giving ["fragile", "gift"]. Python’s sorted() makes the list for you, but .toSorted() needs an array, so in JavaScript it’s two steps.
  • The sort is worth keeping in JavaScript too. A Set keeps the order the shop sent the tags in, so if the next order lists "fragile" first, the Set puts "fragile" first. Sorted, they read the same on every label, and the label matches the Python script’s.
  • Watch out for other values JSON doesn’t know. A phone read as order.customer?.phone, with no ??, is undefined for order 1042, and JavaScript drops the key altogether, where Python’s None prints null. Dates turn into text.

Here’s the end of the Python script. Higher up, it parses order 1042 from ORDER_TEXT into order. The label holds only the order number and the tags here:

Language: Python
tags = set(order["tags"])

label = {
    "order": order["id"],
    "tags": sorted(tags),
}
print(json.dumps(label, indent=2))

Locked learning resources

Join us and get access to thousands of tutorials and a community of expert JavaScript developers.

Unlock This Lesson

Already a member? Sign-In

Locked learning resources

The full lesson is for members only. Join us and get access to thousands of tutorials and a community of expert JavaScript developers.

Unlock This Lesson

Already a member? Sign-In

00:02 The label still has no tags. The Python script sorts them before it prints them. Why? And what does JavaScript write if you hand it a Set instead? The script builds a set from the order’s tags, which drops the repeated gift.

00:20 The label holds only the order number and the tags here, so it fits on screen. It takes the sorted tags, not the set itself. If the label held the set itself, Python’s json.dumps() would refuse it, with a type error.

00:36 And a Python set has no fixed order: the same tags can come out either way round from one run to the next. Sorted, the tags come out the same every time.

00:47 Run it: the label lists fragile, then gift.

00:54 In the JavaScript port, the set becomes a new Set, and the label an object literal. JSON.stringify() turns it into text, indented by two spaces, and console.log() prints it.

01:06 For sorted(), arrays have .toSorted(), which returns a sorted copy. So the tags line ports as it reads. Run it: JavaScript says tags.toSorted is not a function, and stops on that line.

01:24 Why is .toSorted() missing? It’s an array method, and a Set isn’t an array. But a JavaScript Set keeps its tags in the order they arrived: gift, then fragile.

01:36 So it looks as if the sort isn’t needed.

01:40 And if JSON can’t take a Set, surely JavaScript will say so, the way Python does. So it’s tempting to drop the call and pass the Set itself. What happens to the tags when you run it?

01:53 Your turn: pause the video and predict.

02:01 Run it: JavaScript writes an empty object. There’s no error, and no tags, so the courier’s form would get none.

02:12 JSON has no set type. It knows six kinds of value: objects, arrays, strings, numbers, booleans, and null. JSON.stringify() treats a Set like any other object and writes out its properties.

02:29 A Set keeps its tags inside, not as properties, so there’s nothing to write. A Map comes out empty the same way.

02:39 Neither language has a set in JSON, but here they part ways. Python refuses a set. JavaScript writes a Set, or a Map, as an empty object, and says nothing.

02:54 The fix is to convert the Set to an array first. Three dots spread its tags into a new array, the way a star does in a Python list. Then .toSorted() sorts that array: fragile, then gift.

03:09 Python’s sorted() makes the list for you. In JavaScript, .toSorted() needs an array, so it’s two steps.

03:17 Why sort, if the Set keeps its order? It keeps the order the shop sent them in. If the next order lists fragile first, the Set puts fragile first. Sorted, they read the same on every label.

03:32 Run it: the label matches Python’s, line for line.

03:39 Here’s the rule. JSON.stringify() writes plain objects, arrays, strings, numbers, booleans and null. Convert anything richer to one of those first, because JavaScript won’t warn you.

03:53 Watch out for other values JSON doesn’t know. A phone read with optional chaining and no fallback is undefined for order 1042. Python would print null for its None, but JavaScript drops the key altogether.

04:08 And dates turn into text, a topic for later. Next up: Porting the Shipping Label Script. You’ll port most of Marta’s script line by line, from the pasted order to the label with these sorted tags, and check that it prints what the Python script prints.

Become a Member to join the conversation.