Skip to content

fix(sdk): prefer model_dump_json() over json() in JSONEncoder for Pydantic v2#3770

Open
s-zx wants to merge 2 commits intotraceloop:mainfrom
s-zx:fix/3516-pydantic-json-deprecated-use-model-dump-json
Open

fix(sdk): prefer model_dump_json() over json() in JSONEncoder for Pydantic v2#3770
s-zx wants to merge 2 commits intotraceloop:mainfrom
s-zx:fix/3516-pydantic-json-deprecated-use-model-dump-json

Conversation

@s-zx
Copy link

@s-zx s-zx commented Mar 9, 2026

Problem

JSONEncoder.default() calls o.json() when serialising Pydantic model instances. In Pydantic v2, .json() is deprecated in favour of .model_dump_json(), causing a large volume of PydanticDeprecatedSince20 warnings:

PydanticDeprecatedSince20: The `json` method is deprecated; use `model_dump_json` instead.
Deprecated in Pydantic V2.0 to be removed in V3.0.

Any workflow or task decorated with @task/@workflow whose arguments or return values are Pydantic models triggers this warning.

Reported in #3516.

Fix

Check for .model_dump_json() first (Pydantic v2 path) before falling back to .json() (Pydantic v1 path):

# Prefer Pydantic v2 model_dump_json() to avoid deprecation warnings
if hasattr(o, "model_dump_json"):
    return o.model_dump_json()

if hasattr(o, "json"):
    return o.json()

This eliminates the deprecation warnings for Pydantic v2 models without breaking backwards compatibility with Pydantic v1.

Fixes #3516

Summary by CodeRabbit

  • Bug Fixes
    • Improved JSON serialization to better support Pydantic v2, reducing deprecation warnings and improving compatibility.
    • Preserved existing custom JSON handling and fallback behavior to ensure stable outputs when objects lack modern serialization.

…antic v2

Pydantic v2 deprecated the .json() method in favour of .model_dump_json().
Calling .json() on a Pydantic v2 BaseModel instance emits:

    PydanticDeprecatedSince20: The 'json' method is deprecated;
    use 'model_dump_json' instead.

Fix: check for .model_dump_json() first (Pydantic v2 path) before falling
back to .json() (Pydantic v1 path). This eliminates the deprecation warning
without breaking Pydantic v1 compatibility.

Fixes traceloop#3516
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link

coderabbitai bot commented Mar 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aa840919-02df-4a49-9fa7-34a2ecefca6b

📥 Commits

Reviewing files that changed from the base of the PR and between f4e231d and 7e4c459.

📒 Files selected for processing (1)
  • packages/traceloop-sdk/traceloop/sdk/utils/json_encoder.py

📝 Walkthrough

Walkthrough

Update to JSON encoder fallback ordering: prefer Pydantic v2 model_dump() then standard dict() before calling to_json() or falling back to the object's class name; removed use of json() as a fallback.

Changes

Cohort / File(s) Summary
JSON encoder fallback ordering
packages/traceloop-sdk/traceloop/sdk/utils/json_encoder.py
Reordered and updated fallback logic: added o.model_dump() check, added o.dict() check, removed o.json() fallback; retained o.to_json() and class-name fallback. Comments explain preference to avoid Pydantic v2 deprecation warnings.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I hopped through keys and bytes today,
Swapped an old json for a newer way,
model_dump first, then dict with cheer,
No deprecation warnings near—
I nibble bugs and bound away! 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Title check ⚠️ Warning The PR title mentions preferring model_dump_json() over json(), but the actual implementation uses model_dump() and dict() instead of JSON methods to avoid double-serialization. Update the title to accurately reflect the implementation: 'fix(sdk): prefer model_dump() over json() in JSONEncoder for Pydantic v2' to match the actual code changes.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The code changes successfully address all requirements from issue #3516: using model_dump() for Pydantic v2 models and dict() for v1, eliminating deprecation warnings while maintaining backward compatibility.
Out of Scope Changes check ✅ Passed The pull request modifies only json_encoder.py to fix the deprecated Pydantic method calls, which is directly aligned with the issue #3516 scope.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/traceloop-sdk/traceloop/sdk/utils/json_encoder.py`:
- Around line 17-23: The JSONEncoder.default implementation currently uses
Pydantic's model_dump_json() and .json() which return JSON strings and cause
double-encoding; change the branches in JSONEncoder.default to use model_dump()
for Pydantic v2 and .dict() for Pydantic v1 so the method returns native Python
objects (dict/list) instead of serialized strings, i.e., replace checks for
hasattr(o, "model_dump_json") and hasattr(o, "json") to call o.model_dump() and
o.dict() respectively (falling back to existing behavior if those methods are
absent).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 749b32c5-a9cf-4fa4-87bc-ab969932854b

📥 Commits

Reviewing files that changed from the base of the PR and between 93786d9 and f4e231d.

📒 Files selected for processing (1)
  • packages/traceloop-sdk/traceloop/sdk/utils/json_encoder.py

…()/json()

JSONEncoder.default() must return a JSON-serializable Python object (dict,
list, etc.) that the encoder will then serialise. Both model_dump_json()
(Pydantic v2) and .json() (Pydantic v1) return an already-serialised JSON
string; when returned from default() that string is re-serialised as a JSON
string literal, producing double-escaped output like
  "{\"name\": \"John\"}"
instead of
  {"name": "John"}.

Use model_dump() (Pydantic v2) and .dict() (Pydantic v1) instead, which
return plain Python dicts that the encoder serialises correctly. This also
avoids the PydanticDeprecatedSince20 warnings that motivated the previous
change, because model_dump() is the current recommended API.
@s-zx
Copy link
Author

s-zx commented Mar 9, 2026

Good catch — fixed. model_dump_json() and .json() both return a JSON string, so returning them from JSONEncoder.default() caused the string to be double-serialised (escaped into a JSON string literal).

Changed to model_dump() (Pydantic v2) and .dict() (Pydantic v1), which return plain Python dicts that the encoder serialises correctly. This also eliminates the PydanticDeprecatedSince20 warning since model_dump() is the current recommended Pydantic v2 API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🐛 Bug Report: JSONEncoder calling deprecated method json for Pydantic models

2 participants