Convert a JSON feed to an rss feed (RSS 2.0.11). Supports the @xmlns:itunes iTunes RSS extensions and best practices for podcasts, xmlns:dc Dublin Core author names, and the xmlns:content RDF Site Summary 1.0 Modules: Content encoded content extension.
$ npm install jsonfeed-to-rss
const jsonfeedToRSS = require('jsonfeed-to-rss')
const someJSONFeed = require('./load-some-json-feed-data.json')
const rssFeed = jsonfeedToRSS(someJSONFeed) // Returns an rss 2.0.11 formatted json feed
Example input:
{
"version":"https://jsonfeed.org/version/1",
"title":"bret.io log",
"home_page_url":"https://jsonfeed-to-rss.netlify.com",
"feed_url":"https://jsonfeed-to-rss.netlify.com/snapshots/readme-feed.json",
"description": "A simple summary that describes the podcast. It can have a few sentences.\n\nIf there is more than one paragraph, it gets truncated in some contexts.",
"next_url":"https://jsonfeed-to-rss.netlify.com/snapshots/2017.json",
"icon":"https://jsonfeed-to-rss.netlify.com/icon-512x512.png",
"author":{
"name":"Bret Comnes",
"url":"https://bret.io",
"avatar":"https://gravatar.com/avatar/8d8b82740cb7ca994449cccd1dfdef5f?size=512"
},
"_itunes":{
"about":"https://github.com/bcomnes/jsonfeed-to-rss#itunes",
"owner": {
"email": "bcomnes@gmail.com"
},
"image": "https://jsonfeed-to-rss.netlify.com/icon-3000x3000.png",
"category": "Sports & Recreation",
"subcategory": "Outdoor"
},
"items":[
{
"date_published":"2018-04-07T20:48:02.000Z",
"content_html":"<h1>Curam ad aut hactenus dentes cedere vigil</h1>\n<h2>Non Clitorio vertitur cavatur</h2>\n<p>Lorem markdownum edendi, non ad clamant solacia septem ambierantque. Scelus te\nmihi arcum fore nitidam; in dixit de simul.</p>",
"url":"https://jsonfeed-to-rss.netlify.com/a-url-to-a-post",
"id":"https://jsonfeed-to-rss.netlify.com/a-url-to-a-post-2018-04-07T20:48:02.000Z",
"image": "https://jsonfeed-to-rss.netlify.com/a-url-to-a-post/episode-3000x3000.png",
"_itunes": {
"episode": 12
},
"attachments":[
{
"url":"https://jsonfeed-to-rss.netlify.com/a-url-to-a-post/attatchment.mp4",
"mime_type":"audio/mpeg",
"title":"Hey this is a podcast episode",
"duration_in_seconds":12345,
"size_in_bytes":1234
}
]
}
]
}
Example output:
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
<channel>
<atom:link href="https://jsonfeed-to-rss.netlify.com/snapshots/readme-feed-rss.xml" rel="self" type="application/rss+xml"/>
<title>bret.io log</title>
<link>https://jsonfeed-to-rss.netlify.com</link>
<description>A simple summary that describes the podcast. It can have a few sentences.
If there is more than one paragraph, it gets truncated in some contexts.</description>
<language>en-us</language>
<copyright>© 2018 Bret Comnes</copyright>
<pubDate>Sat, 07 Apr 2018 20:48:02 GMT</pubDate>
<category>Sports & Recreation</category>
<category>Outdoor</category>
<generator>jsonfeed-to-rss 1.1.1 (https://github.com/bcomnes/jsonfeed-to-rss#readme)</generator>
<docs>http://www.rssboard.org/rss-specification</docs>
<image>
<url>https://jsonfeed-to-rss.netlify.com/icon-512x512.png</url>
<link>https://jsonfeed-to-rss.netlify.com</link>
<title>bret.io log</title>
</image>
<itunes:author>Bret Comnes</itunes:author>
<itunes:summary>A simple summary that describes the podcast. It can have a few sentences.</itunes:summary>
<itunes:subtitle>A simple summary that describes the podcast.</itunes:subtitle>
<itunes:type>episodic</itunes:type>
<itunes:owner>
<itunes:name>Bret Comnes</itunes:name>
<itunes:email>bcomnes@gmail.com</itunes:email>
</itunes:owner>
<itunes:image href="https://jsonfeed-to-rss.netlify.com/icon-3000x3000.png"/>
<itunes:category text="Sports & Recreation">
<itunes:category text="Outdoor"/>
</itunes:category>
<item>
<title>Curam ad aut hactenus dentes cedere vigil</title>
<link>https://jsonfeed-to-rss.netlify.com/a-url-to-a-post</link>
<dc:creator>Bret Comnes</dc:creator>
<description>Curam ad aut hactenus dentes cedere vigil
Non Clitorio vertitur cavatur
Lorem markdownum edendi, non ad clamant solacia septem ambierantque. Scelus te
mihi arcum fore nitidam; in dixit de simul.</description>
<content:encoded>
<![CDATA[<h1>Curam ad aut hactenus dentes cedere vigil</h1>
<h2>Non Clitorio vertitur cavatur</h2>
<p>Lorem markdownum edendi, non ad clamant solacia septem ambierantque. Scelus te
mihi arcum fore nitidam; in dixit de simul.</p>]]>
</content:encoded>
<guid isPermaLink="false">https://jsonfeed-to-rss.netlify.com/a-url-to-a-post-2018-04-07T20:48:02.000Z</guid>
<pubDate>Sat, 07 Apr 2018 20:48:02 GMT</pubDate>
<enclosure type="audio/mpeg" url="https://jsonfeed-to-rss.netlify.com/a-url-to-a-post/attatchment.mp4" length="1234"/>
<itunes:episodeType>full</itunes:episodeType>
<itunes:title>Curam ad aut hactenus dentes cedere vigil</itunes:title>
<itunes:author>Bret Comnes</itunes:author>
<itunes:episode>12</itunes:episode>
<itunes:subtitle>Curam ad aut hactenus dentes cedere vigil</itunes:subtitle>
<itunes:summary>Curam ad aut hactenus dentes cedere vigil</itunes:summary>
<itunes:image>https://jsonfeed-to-rss.netlify.com/a-url-to-a-post/episode-3000x3000.png</itunes:image>
<itunes:duration>3:25:45</itunes:duration>
</item>
</channel>
</rss>
Coverts a parsed JSON feed into an RSS feed. Returns the string of the rss feed.
Opts include:
{
// a function that returns the rss feed url
feedURLFn: (feedURL, jf) => feedURL.replace(/\.json\b/, '-rss.xml'),
language: 'en-us',
copyright: `© ${now.getFullYear()} ${jf.author && jf.author.name ? jf.author.name : ''}`,
managingEditor,
webMaster,
idIsPermalink: false, // if guid is the permalink, you can set this true
category, // array of categories.. will attempt to use iTunes categories if available
ttl,
skipHours,
skipDays,
itunes: !!jf._itunes // generate RSS feed with iTunes extensions
}
There is only one mapping implemented between jsonfeed and RSS:
item.author.name || jf.author.name
(recommended) maps todc:creator
.
The content:encoded
field is used to store an html
representation of content, and RSS's default description
field is for a plain text representation.
item.content_html
(recommended) maps to aCDATA
encodedcontent:encoded
node.item.content_text || striptags(item.content_html)
(recommended) maps to an escapeddescription
node. When creating an iTunes feed, description is truncated to 4000 characters.
If the itunes
option is set to true
(or if the jsonfeed._itunes
extension object is included in the jsonfeed) the resulting RSS feed will include as many itunes extension tags as possible. You can override/set _itunes
extension fields from the opts.itunes
object.
All _itunes.property
map directly to the RSS itunes:property
extensions, but most have default mappings to standard JSONFeed properties. Its better to rely on the default JSONFeed fields, but you can override these mappings by including explicit _itunes
extension properties in your JSONFeed.
- There are a few extension fields that SHOULD be included, but dont map well. These are marked as (recommended).
- There are fields that dont have a mapping that are definitely optional but CAN be included. These are marked as (optional).
- There are fields that have default and acceptable mappings. These MAY be included but probably not. These are marked as (mapped).
_itunes.owner.email
(recommended) maps toitunes:owner.itunes:email
._itunes.image
(recommended) maps toitunes:image
. Defaults toicon
but theicon
field does not meet the minimum requirements for this field. Theicon
field is a 512x512 image, where iTunes recommends Artwork that must be a minimum size of 1400 x 1400 pixels and a maximum size of 3000 x 3000 pixels, in JPEG or PNG format, 72 dpi, with appropriate file extensions (.jpg, .png), and in the RGB colorspace._itunes.category
(recommended) maps toitunes:category
. Defaults toopts.category[0]
. Must be a valid category._itunes.subcategory
(recommended) maps toitunes:category:itunes:category
. Defaults toopts.category[1]
. Must be a valid subcategory._itunes.explicit
(recommended) maps toitunes:explicit
. Defaults to unset._itunes.type
(optional) maps toitunes:type
. Defaults toepisodic
(newest first). The other option isserial
(oldest first). Details._itunes.complete
(optional) maps toitunes:complete
. Defaults to null. Tells podcast clients to stop updating this feed ️️️forever.⚠️ _itunes.block
(optional) maps toitunes:block
. Defaults to null. Prevents the feed from being added to Apple's podcast directory. Helpful for private or customer specific feeds._itunes.new_feed_url
(optional) maps toitunes:new-feed-url
. Used for moving feeds from an old url to a new url. When generatingnext_url
(the next n older feed items), you could generate the converse url for the previous (newer) n items and store it here._itunes.author
(mapped) maps toitunes:author
. Defaults toauthor.name
._itunes.summary
(mapped) maps toitunes:summary
. Defaults to the first paragraph of the generateddescription
rss field._itunes.subtitle
(mapped) maps toitunes:subtitle
. Defaults to the first sentence of the generateditunes:summary
._itunes.owner.name
(mapped) maps toitunes:owner.itunes:name
. Defaults toauthor.name
.
_itunes.episode
(recommended) maps toitunes:episode
. No fallback. Must be an integer > 0. Its recommended you put episode numbers here, instead of in the title._itunes.season
(optional) maps toitunes:season
._itunes.episode_type
(optional) maps toitunes:episodeType
, but must be one offull
,trailer
, orbonus
. Defaults tofull
._itunes.block
(optional) maps toitunes:block
. Defaults to null. Prevents the item from being added to Apple's podcast directory. "For example, you might want to block a specific episode if you know that its content would otherwise cause the entire podcast to be removed from Apple Podcasts."_itunes.is_closed_captioned
(optional) maps toitunes:isClosedCaptioned
._itunes.explicit
(optional) maps toitunes:explicit
. Defaults to null._itunes.title
(mapped) maps toitunes:title
. Falls back toitem.title
and then thegenerateTitle
function._itunes.author
(mapped) maps toitunes:author
. Falls back toauthor.name || jf._itunes.author || jf.author.name
._itunes.subtitle
(mapped) maps toitunes:subtitle
. Defaults to the first sentence of the generated_itunes.summary
._itunes.summary
(mapped) maps toitunes:summary
. Defaults to the first paragraph of the generated plaintext description of the item._itunes.duration
(mapped) maps toitunes:duration
. Defaults toattachment.duration_in_seconds
formatted as HH:MM:SS._itunes.image
(mapped) maps toitunes:image
. Defaults toimage
. Artwork must be a minimum size of 1400 x 1400 pixels and a maximum size of 3000 x 3000 pixels, in JPEG or PNG format, 72 dpi, with appropriate file extensions (.jpg, .png), and in the RGB colorspace. JSONFeed has no defined image restrictions on theimage
field, so it can be safely used for this purpose.
- JSON Feed: Mapping RSS and Atom to JSON Feed
- rssboard.org/rss-specification
- Really Simple Syndication Best Practices Profile
- RSS validator.w3.org
- AtomEnabled: Developers > Syndication
- Why RSS Content Module is Popular
- RSS tags for Podcasts Connect
- Podcast best practices
- Podcasts Connect categories
- Apple Create a podcast
- Apple RSS feed sample
- Apple Requirements - Podcasts Connect Help
- Apple Podcasts - What’s New in iOS 11 - 2017 (mirror)
- Apple Podcasts Identity Guidelines
- podbase Podcast Validator
- Apple podcasts: Whats new
- reference/datcast.xml
- reference/podcast.xml
- reference/rss-2.0-sample.xml
- reference/rss20.xml
- reference/scripting.rss