JSON
Python
Unicode
String Handling
Data Parsing

How to get string objects instead of Unicode from JSON

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

This question only makes sense if you are precise about the Python version. In Python 3, str is Unicode text already, so asking for "string instead of Unicode" usually means you actually want bytes; in Python 2, str and unicode were separate types, which is why older answers often sound different from modern code.

What json.loads Returns

In Python 3, the json module decodes JSON strings into Python str objects.

python
1import json
2
3payload = '{"name": "Ada", "city": "London"}'
4data = json.loads(payload)
5
6print(type(data["name"]))
7print(data["name"])

Output:

text
<class 'str'>
Ada

That str value is Unicode text. There is no second "plain string" text type in Python 3.

If You Actually Need Bytes

Sometimes the real requirement is not "non-Unicode text" but raw encoded bytes for a legacy API, file format, or socket protocol. In that case, decode the JSON normally and then encode the fields you need.

python
1import json
2
3payload = '{"name": "Ada"}'
4data = json.loads(payload)
5
6name_text = data["name"]
7name_bytes = name_text.encode("utf-8")
8
9print(type(name_text))
10print(type(name_bytes))
11print(name_bytes)

Output:

text
<class 'str'>
<class 'bytes'>
b'Ada'

This is the correct boundary: JSON gives you text, and you explicitly choose an encoding when you need bytes.

Why Python 2 Answers Look Different

In Python 2:

  • 'str meant a byte string'
  • 'unicode meant text'

That is why older answers often used recursive conversion helpers after json.loads. A common pattern looked like this:

python
1def to_utf8(value):
2    if isinstance(value, unicode):
3        return value.encode("utf-8")
4    if isinstance(value, list):
5        return [to_utf8(item) for item in value]
6    if isinstance(value, dict):
7        return {to_utf8(k): to_utf8(v) for k, v in value.iteritems()}
8    return value

That pattern is historical. It is not the right default for Python 3 because text handling changed fundamentally.

Do Not Fight Unicode in Python 3

JSON is a text format. Python 3's json.loads returning Unicode text is the correct behavior, not a problem to work around.

For example:

python
1import json
2
3payload = '{"greeting": "Olá"}'
4data = json.loads(payload)
5
6print(data["greeting"])
7print(len(data["greeting"]))

Working with text as text avoids many encoding bugs. If you convert everything to bytes too early, you now have to remember the encoding at every later step.

The better mental model is:

  • use str for text inside Python
  • use bytes only at I/O boundaries

Handling Nested Data

If you truly must convert every string value in a decoded Python 3 JSON object to bytes, do it explicitly and recursively so the behavior is obvious.

python
1import json
2
3def encode_strings(value):
4    if isinstance(value, str):
5        return value.encode("utf-8")
6    if isinstance(value, list):
7        return [encode_strings(item) for item in value]
8    if isinstance(value, dict):
9        return {
10            encode_strings(key): encode_strings(item)
11            for key, item in value.items()
12        }
13    return value
14
15payload = '{"name": "Ada", "tags": ["math", "logic"]}'
16data = json.loads(payload)
17encoded = encode_strings(data)
18
19print(encoded)

This works, but use it only when another system truly demands bytes. It makes ordinary Python data handling less convenient because dictionary keys and values stop being normal text strings.

Serializing Back to JSON

When writing JSON, keep the data as normal Python str values and let json.dumps handle encoding rules.

python
1import json
2
3data = {"name": "Ada", "city": "London"}
4text = json.dumps(data, ensure_ascii=False)
5
6print(text)

If you need bytes to send over the network, encode the final JSON string:

python
wire_payload = text.encode("utf-8")

This is cleaner than forcing all internal values to bytes before serialization.

Common Pitfalls

  • Assuming Python 3 has a separate non-Unicode text string type. It does not; str already represents Unicode text.
  • Converting all decoded JSON strings to bytes too early, then fighting encoding issues throughout the rest of the program.
  • Reading old Python 2 advice and applying it unchanged to Python 3 code.
  • Forgetting that JSON is a text format and that bytes are usually only needed at file, network, or legacy API boundaries.
  • Mixing str and bytes in comparisons or concatenation, which causes errors and confusing bugs in Python 3.

Summary

  • In Python 3, json.loads already returns normal str objects, and those are Unicode text.
  • If you want raw bytes, encode the specific values explicitly with an encoding such as UTF-8.
  • Python 2 treated str and unicode differently, which is why older answers often recommend recursive conversion.
  • Keep text as str inside Python 3 programs and convert to bytes only at I/O boundaries.
  • The right fix is usually clearer type handling, not trying to remove Unicode from JSON parsing.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.