Data Sources, Engineering, and Deployment
Acquire data from files, web, and databases; then test, package, version, and deploy reliable services.
Content
JSON and XML Parsing
Versions:
Watch & Learn
AI-discovered learning video
JSON and XML Parsing — Practical Guide for Python Data Workflows
"Parsing isn't just about reading files — it's the polite conversation your pipeline has with messy reality."
You're already comfortable training models with PyTorch and serving them (remember that glorious GPU-accelerated training). Now let's talk about the raw materials feeding those models and the outputs you send back: JSON and XML. These are everywhere — APIs, logs, config files, legacy SOAP services, and the output of the microservice that returns your model predictions. If your parser is weak, your whole pipeline gets the hiccups.
What this lesson covers (quick preview)
- Why JSON vs XML matters in data science pipelines
- Practical Python tools for parsing and streaming large files
- Flattening and normalizing nested JSON for ML features
- Safe XML parsing (don’t let XXE ruin your day)
- Deployment tips: efficient serializing and streaming model outputs
Why this matters (and where you've seen it)
- Model serving: REST APIs often accept JSON requests and return JSON predictions. You learned to serve models — now ensure the payloads are clean.
- Data engineering: ETL jobs ingest JSON logs, XML feeds, and convert them to Parquet/CSV for training.
- Legacy integration: Many enterprise systems still use XML (SOAP, RSS, vendor feeds). You’ll need to parse or convert them.
If you skip careful parsing, you get NaNs, wrong schema, or an embarrassingly bad model input.
JSON Parsing: The good, the nested, and the streaming
Basic parsing (the comfy part)
Use the standard library for small files:
import json
with open('data.json') as f:
obj = json.load(f) # reads the whole JSON into memory
But JSONs frequently nest arrays and objects — for ML you often need a flat table.
Flatten nested JSON for features
Use pandas.json_normalize to convert a list-of-records JSON into a DataFrame.
import pandas as pd
data = [
{'id': 1, 'user': {'age': 30, 'name': 'A'}, 'events': [{'type': 'click'}]},
{'id': 2, 'user': {'age': 22, 'name': 'B'}, 'events': []}
]
df = pd.json_normalize(data, sep='_')
# columns like user_age, user_name, events (still nested list)
For nested arrays (events), normalize further or explode the column:
df_exploded = df.explode('events').reset_index(drop=True)
Streaming large JSON (memory saving)
For multi-GB JSON (logs, exported datasets), don't load it all. Use ijson or jsonlines.
- NDJSON / JSON Lines (one JSON object per line) is ideal for streaming.
Example: read NDJSON into DB or DataFrame in chunks:
import json
with open('logs.ndjson') as f:
for line in f:
rec = json.loads(line)
process(rec) # small constant-memory processing
For a single huge JSON array use ijson:
import ijson
with open('huge.json', 'rb') as f:
for item in ijson.items(f, 'item'):
process(item)
XML Parsing: the cranky but necessary sibling
XML can contain mixed content, namespaces, attributes, CDATA, and SOAP envelopes. Treat it with respect.
Safe parsing
XML has security pitfalls (XXE attacks). Use defusedxml for untrusted inputs:
from defusedxml import ElementTree as DET
root = DET.parse('feed.xml').getroot()
If you control the XML source and speed matters, lxml is fast. For streaming, use lxml.etree.iterparse.
Navigating elements and namespaces
XML namespaces make tag names look like {http://...}tag. Use namespace maps:
import xml.etree.ElementTree as ET
ns = {'ns': 'http://example.com/schema'}
root = ET.parse('file.xml').getroot()
for el in root.findall('.//ns:item', ns):
val = el.find('ns:name', ns).text
Streaming large XML
Use iterparse to avoid building full tree:
import xml.etree.ElementTree as ET
for event, elem in ET.iterparse('big.xml', events=('end',)):
if elem.tag == 'record':
process(elem)
elem.clear() # free memory
Converting between XML and JSON
- Convert when integrating legacy systems into modern JSON-based pipelines.
- Beware: XML attributes vs text, mixed content, and arrays are ambiguous — define a stable mapping.
Simple conversion with xmltodict:
import xmltodict, json
with open('feed.xml') as f:
doc = xmltodict.parse(f.read())
json_str = json.dumps(doc)
Then normalize with pandas or custom logic.
Validation, Schemas, and Type Safety
- JSON Schema validates payload shape and types — great for APIs.
- XSD validates XML structure — often used with SOAP.
Use these in your CI or API gateway so bad payloads are rejected early rather than poisoning training data.
Deployment tips (practical, no fluff)
- Always set content-type headers: application/json or application/xml.
- For large prediction responses, stream with chunked transfer or NDJSON for long lists.
- Compress responses (gzip) to save bandwidth.
- When returning model outputs (e.g., from Flask/FastAPI), convert tensors to lists first:
from fastapi import FastAPI
import torch
app = FastAPI()
@app.post('/predict')
async def predict(payload: dict):
# process payload -> tensor -> model -> out
out = model(input_tensor)
return {'pred': out.detach().cpu().tolist()} # JSON-safe
- Prefer JSON Lines for logs and streaming predictions.
- For storage and analytics transforms, convert to columnar formats (Parquet) after parsing.
Common gotchas & how to survive them
- Unexpected nulls or missing keys -> use .get and provide defaults
- Mixed-type arrays -> enforce schema or cast before feeding model
- Encoding issues (BOM, weird charsets) -> open files with correct encoding='utf-8-sig'
- XML external entities -> always use defusedxml for untrusted input
Quick checklist before training or serving
- Validate incoming data shape (JSON Schema/XSD)
- Flatten nested JSON into feature columns
- Stream large inputs, don't load > memory
- Sanitize and encode outputs for API consumers
- Compress and set correct content-type for deployed endpoints
Key takeaways
- Use the right tool for the job: json/pandas/json_normalize for typical JSON, ijson/jsonlines for streaming, defusedxml/lxml for XML.
- Flatten early: convert nested payloads into a stable tabular schema for ML training.
- Validate and secure: schemas catch errors early; defusedxml prevents XXE.
- Think about deployment: streaming, compression, and JSON-safe model outputs matter for latency and stability.
"Parsing is the unsung data-scientist skill — get it right, and your models stop blaming the data and start showing what they really learned."
If you want, I can:
- Give a hands-on notebook that reads a 5GB NDJSON file in streaming mode and writes Parquet in chunks
- Show converting a SOAP XML response into a clean DataFrame suitable for training
Which one next?
Comments (0)
Please sign in to leave a comment.
No comments yet. Be the first to comment!