How to convert json posts to an rss 2.0 feed
- Step 1Format dates to RFC-822 first — RSS
pubDatemust be RFC-822, e.g.Mon, 01 Jun 2026 14:30:00 GMT. The converter does not transform dates — it copies them verbatim. Convert your ISO-8601 timestamps to RFC-822 in your CMS export or a script before pasting. - Step 2Shape the JSON as an rss document — Build
{ "rss": { "@version": "2.0", "channel": { "title": "...", "link": "...", "description": "...", "item": [ ... ] } } }. Then set the Root element option torss. The@versionkey becomes the required version attribute. - Step 3Name JSON keys to match RSS elements — There are no field-mapping dropdowns. Each
<item>needstitle,link, and ideallypubDate,description, andguid. Rename your CMS keys (e.g.publishedAt→pubDate,excerpt→description) in the JSON before converting — use json-key-renamer to do it in bulk. - Step 4Decide how to handle HTML descriptions — HTML in a
descriptionis entity-escaped, not CDATA-wrapped. Most readers decode the entities fine. If a target aggregator requires literal CDATA, do a find/replace after download to wrap those values in<![CDATA[ ... ]]>. - Step 5Choose indent and convert — Pick 2 spaces for a readable feed. Keep XML declaration on. Click Convert to XML, Download, and rename to
feed.xmlorrss.xml. - Step 6Serve and subscribe — Serve the file from your site (e.g.
/feed.xml) withContent-Type: application/rss+xml. Point feed readers or podcast directories at the full absolute URL, and validate it with the W3C Feed Validator.
JSON shape → RSS 2.0 XML
Structural mapping with Root element = rss. Values are copied verbatim; the converter does not reformat dates or wrap text in CDATA.
| JSON | XML | Tool behaviour |
|---|---|---|
{ "rss": { "@version": "2.0", ... } } | <rss version="2.0">... | @version → version attribute |
"item": [ {...}, {...} ] | Two <item> blocks | item array repeats under its own key |
"pubDate": "Mon, 01 Jun 2026 14:30:00 GMT" | <pubDate>Mon, 01 Jun 2026 14:30:00 GMT</pubDate> | Verbatim — you must pre-format to RFC-822 |
"description": "<p>Hi</p>" | <description><p>Hi</p></description> | HTML entity-escaped, NOT CDATA-wrapped |
"link": "https://x/?a=1&b=2" | <link>https://x/?a=1&b=2</link> | & escaped to & |
"enclosure": { "@url": "...", "@length": "123", "@type": "audio/mpeg" } | <enclosure url="..." length="123" type="audio/mpeg"/> | @-prefixed keys → attributes; self-closing |
Formatting the converter leaves to you
RSS requirements that are NOT automated. Earlier descriptions claiming RFC-822 conversion, CDATA wrapping, or field-mapping dropdowns are inaccurate.
| RSS requirement | Automated? | How to handle |
|---|---|---|
ISO-8601 → RFC-822 pubDate | No | Convert dates in your CMS export / a script first |
CDATA-wrap <description> | No (entity-escaped instead) | Post-process if a reader demands CDATA |
Rename publishedAt → pubDate | No | Rename keys with json-key-renamer |
version="2.0" attribute | Only via @version key | Add @version to the rss object |
Escape &, <, > in values | Yes | Automatic entity escaping |
Cookbook
Real JSON post arrays and the exact RSS 2.0 XML the converter produces. Set root = rss, add @version, nest an item array, and pre-format dates.
Two-post feed with channel metadata
ExampleWrap the channel and items under rss. The @version key gives the required version attribute; the item array repeats per post.
Input JSON:
{ "rss": { "@version": "2.0", "channel": {
"title": "My Blog",
"link": "https://example.com",
"description": "Latest posts",
"item": [
{ "title": "Hello", "link": "https://example.com/1",
"pubDate": "Mon, 01 Jun 2026 09:00:00 GMT" },
{ "title": "World", "link": "https://example.com/2",
"pubDate": "Tue, 02 Jun 2026 09:00:00 GMT" }
]
} } }
Options: Root element = rss, indent = 2
Output XML:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>My Blog</title>
<link>https://example.com</link>
<description>Latest posts</description>
<item>
<title>Hello</title>
<link>https://example.com/1</link>
<pubDate>Mon, 01 Jun 2026 09:00:00 GMT</pubDate>
</item>
<item>
<title>World</title>
<link>https://example.com/2</link>
<pubDate>Tue, 02 Jun 2026 09:00:00 GMT</pubDate>
</item>
</channel>
</rss>Podcast enclosure via @-prefixed attributes
ExampleAn <enclosure> is all attributes. Model them with @url, @length, @type. The element self-closes because it has no text content.
Input JSON (one item):
{ "title": "Ep 1",
"enclosure": { "@url": "https://cdn/ep1.mp3",
"@length": "10485760",
"@type": "audio/mpeg" } }
Output XML (fragment):
<item>
<title>Ep 1</title>
<enclosure url="https://cdn/ep1.mp3" length="10485760" type="audio/mpeg"/>
</item>HTML description is escaped, not CDATA
ExampleThere is no CDATA option. HTML in a description is entity-escaped; readers decode it back. Post-process only if an aggregator insists on literal CDATA.
Input JSON:
{ "description": "<p>Read <a href=\"/x\">more</a></p>" }
Output XML:
<description><p>Read <a href="/x">more</a></p></description>Pre-format ISO dates to RFC-822 first
ExampleThe converter copies dates verbatim. If you feed ISO-8601, the feed validates as invalid pubDate. Convert before pasting.
WRONG (ISO passed straight through): "pubDate": "2026-06-01T09:00:00Z" → <pubDate>2026-06-01T09:00:00Z</pubDate> (invalid for RSS) RIGHT (pre-format to RFC-822 upstream): "pubDate": "Mon, 01 Jun 2026 09:00:00 GMT" → <pubDate>Mon, 01 Jun 2026 09:00:00 GMT</pubDate>
guid with isPermaLink attribute
ExampleA <guid> often carries an isPermaLink attribute plus text. Combine an @isPermaLink key with #text.
Input JSON (one item):
{ "title": "Post",
"guid": { "@isPermaLink": "false", "#text": "urn:uuid:abc-123" } }
Output XML (fragment):
<item>
<title>Post</title>
<guid isPermaLink="false">urn:uuid:abc-123</guid>
</item>Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
pubDate given as an ISO-8601 timestamp
Invalid pubDateRSS requires RFC-822 dates. The converter copies dates verbatim — it does NOT convert ISO-8601, contrary to older descriptions. An ISO pubDate like 2026-06-01T09:00:00Z makes the feed fail RSS validators. Format dates to Mon, 01 Jun 2026 09:00:00 GMT in your export or a pre-step.
You expected CDATA around descriptions
By designThere is no CDATA option. HTML in a <description> is entity-escaped (<p> → <p>). Conformant readers decode entities, so the rendered content is identical. If a specific aggregator requires literal CDATA, find/replace those values to wrap them in <![CDATA[ ... ]]> after download.
Missing version attribute
Invalid feedRSS 2.0 requires <rss version="2.0">. The converter only adds it if you include @version on the rss object. Forget it and you get a bare <rss> that validators reject. Always add "@version": "2.0".
Field names don't match RSS element names
Wrong elementsThere are no field-mapping dropdowns — element names come straight from JSON keys. If your CMS uses publishedAt and excerpt, you get <publishedAt> and <excerpt> elements, which readers ignore. Rename keys to pubDate / description first with json-key-renamer.
Empty item array
OmittedAn empty "item": [] produces no <item> elements at all — you get a channel with no entries. A feed with zero items is valid but pointless; check that your CMS query actually returned posts before converting.
Ampersand in a link or title
Escaped (correct)A literal & in a link or title is escaped to &, keeping the feed well-formed. Don't pre-escape in your JSON or you'll get &amp;. Other specials (<, >, ", ') are escaped too.
Invalid JSON pasted
Parse errorInput runs through JSON.parse; a trailing comma, single quotes, or an unquoted key throws and nothing converts. Many CMS exports are fine, but partial/streamed payloads aren't — repair with json-format-fixer.
Large feed over the free limit
Blocked (Pro)JSON to XML is Pro. Free inputs are capped at 2 MB; Pro at 100 MB. A feed with full HTML bodies for hundreds of posts can exceed 2 MB of JSON, so it may need Pro. Conversion runs in-browser regardless.
Frequently asked questions
How do I get repeated <item> elements?
Nest an item array under channel: { "channel": { "item": [ {...}, {...} ] } }. An array inside an object repeats under its own key, so each entry becomes an <item>. Wrap the whole thing in { "rss": { "@version": "2.0", "channel": {...} } } and set the root to rss.
Does the tool convert ISO dates to RFC-822 pubDate?
No. Dates are copied verbatim — there is no date transformation. RSS requires RFC-822 (Mon, 01 Jun 2026 09:00:00 GMT), so convert your ISO-8601 timestamps before converting. An unconverted ISO pubDate fails RSS validators.
Are descriptions wrapped in CDATA?
No. HTML in a <description> is entity-escaped (<p> → <p>). Standards-conformant readers decode the entities, so the content renders the same. If a target aggregator specifically requires literal CDATA, wrap those values in <![CDATA[ ... ]]> after download — there's no CDATA option in the tool.
Can I map my CMS field names to RSS elements?
Not in this tool — element names come directly from JSON keys, and there are no field-mapping dropdowns. Rename your keys first: publishedAt → pubDate, excerpt → description, etc. json-key-renamer does bulk renames in one pass.
How do I add a podcast enclosure?
Model it as an all-attributes element using the @ prefix: { "enclosure": { "@url": "...", "@length": "10485760", "@type": "audio/mpeg" } }. With no text content it serializes as a self-closing <enclosure url="..." length="..." type="..."/>, which Apple Podcasts and Spotify ingestion accept.
How do I set the required RSS version attribute?
Add "@version": "2.0" to the rss object. The @ attribute prefix turns it into version="2.0" on <rss>. Without it the feed is invalid. The same @ mechanism handles isPermaLink on <guid> and domain on <category>.
Can I emit namespaced elements like media:content or dc:creator?
The converter writes element names verbatim, so a key "media:content" produces <media:content> — but it does NOT add the xmlns:media declaration. Add the namespace yourself via an @xmlns:media key on the rss object so the prefix resolves. Same approach for dc:creator / xmlns:dc.
RSS 2.0 vs Atom — which should I build?
RSS 2.0 has the widest reader and podcast support; Atom is stricter and better for i18n. This tool can emit either shape — it's structural — but you model the elements yourself. For maximum compatibility, build RSS 2.0; switch to Atom only if a specific aggregator requires it.
Why is my feed showing escaped HTML as literal tags?
If a reader shows <p> as text, it's reading the description as plain text rather than HTML. That's a reader/feed-config issue, not the escaping — the escaping is correct XML. Either the reader needs the content in content:encoded with CDATA, or the description should be plain text. Adjust the feed shape accordingly.
Will my draft content be uploaded?
No. Generation is fully client-side. Unpublished drafts and any API keys present in the JSON never reach JAD Apps servers. Only an anonymous run counter (no content) is recorded for signed-in dashboard stats.
How large a feed can I convert?
JSON to XML is Pro. Free tier caps the input at 2 MB; Pro at 100 MB. Feeds with full HTML article bodies can exceed 2 MB quickly, so large feeds may need Pro. Everything runs in the browser, so the ceiling on huge feeds is browser memory.
How do I turn an existing RSS feed back into JSON?
Use xml-to-json to parse a feed into JSON, with removeNSPrefix to drop media: / dc: prefixes. To pull, say, every item title, json-path-extractor can run $.rss.channel.item[*].title against the parsed result.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.