合并从wordpress导出的两个Json文件
Posted
技术标签:
【中文标题】合并从wordpress导出的两个Json文件【英文标题】:Combine two Json files exported from wordpress 【发布时间】:2018-10-09 10:21:47 【问题描述】:我有两个从 wordpress 导出的具有相应 ID 的 Json 文件,我想将它们组合成一个 Json 文件,这样我就可以将它带入我正在使用 Gatsby JS 构建的网站中。其中一个文件是posts.json
,另一个是postsMeta.json
。 postsMeta 中的 post_id 对应 Posts
如何最好地合并两者?我可以在 js 中运行某种 for
循环吗?我该怎么做?我在 Windows 上是否有某种 json explorer 可以帮助我做到这一点。
最后,我还想删除一些不必要的字段,例如 posts json 中的 post_parent
以及 postsMeta json 中的 meta_key
.
好的,希望这已经足够清楚了,在此先感谢。
这是两个文件中第一个对象对应对的示例
posts.json
"ID":"19","post_author":"2","post_date":"2010-12-31 23:02:04","post_date_gmt":"2010-12-31 23:02:04","post_content":"Harry Potter was not available for the first sitting of the Halloween Picture. I hope everyone had a safe and fun Halloween. Tomorrow is picture retake day, please send back your previous prints if you want retakes. It is also hot lunch. See You tomorrow!","post_title":"Happy Halloween","post_excerpt":"","post_status":"publish","comment_status":"open","ping_status":"open","post_password":"","post_name":"happy-halloween","to_ping":"","pinged":"","post_modified":"2011-01-03 05:26:11","post_modified_gmt":"2011-01-03 05:26:11","post_content_filtered":"","post_parent":"0","guid":"http:\/\/localhost\/mrskitson.ca_wordpress\/?p=19","menu_order":"0","post_type":"post","post_mime_type":"","comment_count":"1",
postsMeta.json
"meta_id":"27","post_id":"19","meta_key":"large_preview","meta_value":"http:\/\/www.mrskitson.ca\/wp-content\/uploads\/2010\/12\/halloween.jpg",
更新:
this 是尝试用当前答案解决这个问题,您可以在那里编辑代码。
【问题讨论】:
您的问题在下面的答案中产生的非常有趣的示例代码,为每个人 +1 :) 用你需要的字段创建一个新的json,遍历第一个json,检查第二个json中的每一行,然后当键匹配时,在新的json中填充当前的“行”,然后从第一个 json 中的第二个“行”开始。 【参考方案1】:如何最好地合并两者?
您是否强制合并两个 JSON 文件/数据?
因为您可以只在脚本中要求或加载 JSON 数据(甚至将它们放在 html
中),然后获取特定元字段/键的元值,这个 function
可以做到这一点:
// `single` has no effect if `meta_key` is empty.
function getPostMeta( post_id, meta_key, single )
let id = String( post_id ),
pm = [];
postsMeta.map( m =>
let a = ( ! meta_key ) ||
( meta_key === m.meta_key );
if ( a && id === m.post_id )
pm.push( m );
);
let meta = ,
mk = ;
pm.map( m =>
let k = m.meta_key, v;
if ( undefined === meta[ k ] )
meta[ k ] = m.meta_value;
else
v = meta[ k ];
if ( undefined === mk[ k ] )
meta[ k ] = [ v ];
mk[ k ] = 1;
meta[ k ].push( m.meta_value );
m[ k ]++;
);
pm = null;
mk = meta_key ? mk[ meta_key ] : null;
if ( mk )
return single ?
meta[ meta_key ][0] : // Returns a single meta value.
meta[ meta_key ]; // Returns all the meta values.
return meta_key ?
meta[ meta_key ] : // Returns the value of the `meta_key`.
meta; // Or returns all the post's meta data.
我用来测试的数据:(注意上面的postsMeta
/getPostMeta()
函数)
// Array of `post` objects.
const posts = ["ID":"19","post_author":"2","post_date":"2010-12-31 23:02:04","post_date_gmt":"2010-12-31 23:02:04","post_content":"Harry Potter was not available for the first sitting of the Halloween Picture. I hope everyone had a safe and fun Halloween. Tomorrow is picture retake day, please send back your previous prints if you want retakes. It is also hot lunch. See You tomorrow!","post_title":"Happy Halloween","post_excerpt":"","post_status":"publish","comment_status":"open","ping_status":"open","post_password":"","post_name":"happy-halloween","to_ping":"","pinged":"","post_modified":"2011-01-03 05:26:11","post_modified_gmt":"2011-01-03 05:26:11","post_content_filtered":"","post_parent":"0","guid":"http:\/\/localhost\/mrskitson.ca_wordpress\/?p=19","menu_order":"0","post_type":"post","post_mime_type":"","comment_count":"1"];
// Array of `meta` objects.
const postsMeta = ["meta_id":"27","post_id":"19","meta_key":"large_preview","meta_value":"http:\/\/www.mrskitson.ca\/wp-content\/uploads\/2010\/12\/halloween.jpg","meta_id":"28","post_id":"19","meta_key":"many_values","meta_value":"http:\/\/facebook.com","meta_id":"29","post_id":"19","meta_key":"many_values","meta_value":"http:\/\/twitter.com","meta_id":"30","post_id":"19","meta_key":"many_values","meta_value":"http:\/\/linkedin.com"];
示例:(请参阅this Fiddle 进行演示)
// In these examples, we are retrieving the meta value for the post #19 (i.e. ID is 19).
// Retrieve a single value.
// Returns mixed; string, number, etc.
let url = getPostMeta( 19, 'large_preview', true );
console.log( url );
// Retrieve all meta values.
// Always returns an array of values.
let ms = getPostMeta( 19, 'many_values' );
console.log( ms, ms[0] );
// Retrieve all meta data.
// Always returns an object with meta_key => meta_value pairs. I.e. key => value, ...
let ma = getPostMeta( 19 );
console.log( ma, ma.large_preview, ma.many_values[0] );
但如果你真的必须合并 JSON 数据,你可以这样做:(再次,参见 the same Fiddle 上的演示)
// Here we modify the original `posts` object.
posts.map( p =>
// Add all the post's meta data.
p.meta = getPostMeta( p.ID );
// Delete items you don't want..
delete p.post_parent;
delete p.menu_order;
// delete ...;
);
console.log( JSON.stringify( posts[0].meta ) ); // posts[0].meta = object
console.log( posts[0].post_parent, posts[0].menu_order ); // both are undefined
然后,如果您想复制粘贴新的/合并 JSON 数据:
JSON.stringify( posts );
但是如果你真的只是想对帖子的元数据做点什么,你可以遍历 posts
对象并做这件事;例如:
// Here the original `posts` object is not modified, and that we don't
// (though you can) repeatedly call `getPostMeta()` for the same post.
posts.map( p =>
// Get all the post's meta data.
let meta = getPostMeta( p.ID );
// Do something with `meta`.
console.log( meta.large_preview );
);
console.log( JSON.stringify( posts[0].meta ) ); // posts[0].meta = undefined
console.log( posts[0].post_parent, posts[0].menu_order ); // both still defined
// posts[0].meta wouldn't be undefined if of course posts[0] had a `meta` item,
// which was set in/via WordPress...
【讨论】:
【参考方案2】:如果您可以在 js 中执行此操作,那么使用 Array#map
有一个非常简单的方法。如果您简化您的问题,您实际上是在询问如何在帖子的每个条目下添加此元数据,并且只获取您想要的字段。
我假设 posts.json 实际上是一个数组(例如["ID":"19"....
)。
// Load these server-side, fetch them remotely, copy-paste, etc.
// I'll require them here for simplicity
const posts = require('./posts.json');
const postsMeta = require('./postsMeta.json');
// Build a Map so we can quickly look up the metas by post_id
// Extract what we need by destructuring the args
const metaByPost = postsMeta.reduce((a,
post_id: id,
meta_value: value,
) => a.set(id,
value,
/* anything else you want in here */,
), new Map());
const mergedPosts = posts.map(post => (
// Spread in the post
...post,
// Spread in the meta content
...metaByPost.get(post.ID),
// Undefine the props we don't want
post_parent: undefined,
));
我不喜欢手动将东西设置为未定义 - 我认为明确说明您将包含哪些道具会更好,而不是加载所有内容并取消定义某些道具。
【讨论】:
这里已经有点卡住了。如果我需要在服务器端加载这些文件,我正在考虑使用meteor将它们放在服务器文件夹中并通过路径导入它们,还是我仍然使用const posts
格式我也不知道在里面放什么mergedPosts
部分在帖子中说“传播”,我真的只是把值 post
... 等等这是否意味着 mergedPosts
变量将是两个组合 json 文件的数组?
@AndersKitson 看看这个以获取更多关于点差的信息:developer.mozilla.org/en-US/docs/Web/javascript/Reference/…
该代码所做的是获取帖子中的属性,该帖子的元内容中的属性,然后将它们放在一起构建一个新对象。对象道具总是设置为最后一个,因此post_parent: undefined
将设置为 undefined 如果它是最后一个。
好的,...
是实际的传播语法吗?我假设你把它作为填充缺失的部分。另外,当您说加载这些服务器端时?我可以在 Node js 中做到这一点吗?或者在像流星这样的框架中,或者你是否建议另一种方式?
我尝试在服务器端的故障上运行它,你可以在这里看到它glitch.com/edit/#!/join/ca634d31-d3eb-4fe0-a8fb-cce34f4d862c我得到一个Map is not defined error
【参考方案3】:
直接在 Chrome DevTools 控制台中试试这个 sn-p:
(function(
postsUrl='https://cdn.glitch.com/61300ea6-6cc4-4cb6-a62f-31adc62ea5cc%2Fposts.json?1525386749382',
metaUrl='https://cdn.glitch.com/61300ea6-6cc4-4cb6-a62f-31adc62ea5cc%2Fpostmeta.json?1525386742630'
)
Promise.all([
fetch(postsUrl).then(r => r.json()),
fetch(metaUrl).then(r => r.json()),
]).then(([postsResponse, metaResponse]) =>
// Inspected the actual JSON response to come up with the data structure
const posts = postsResponse[2].data;
const meta = metaResponse[2].data;
const metaByPostId = meta.reduce((accum, el) =>
accum[el.post_id] = el;
return accum;
, );
const transformedPosts = posts.map(post =>
const merged =
...post,
...(metaByPostId[post.ID] || ),
;
delete merged.post_parent;
// delete any other fields not wanted in the result
return merged;
);
console.log(transformedPosts);
);
)();
相应地替换 URL,我在这里使用了 Glitch 示例中的那些
如评论所述,实际数据隐藏在response[2].data
中。使用网络选项卡/解析视图查看结构
如果您希望将结果复制到剪贴板,而不是记录到控制台,请将 console.log
替换为 copy
【讨论】:
嘿,感谢您的帮助,我在本地运行时收到了TypeError: meta is undefined
。我尝试在 Glitch 上运行它,但出现错误 The page’s settings blocked the loading of a resource
有任何想法。
这很可能意味着对metaUrl
的请求失败,然后const meta = metaResponse[2].data
失败。你可以通过观察 Devtools / Network 来发现。可能是浏览器扩展,尝试隐身会话。我刚刚在 Chrome 上尝试过,它对我有用。或者,仅获取内部函数(const posts = JSON.parse('<your data here >'); const meta = JSON.parse('<meta data>'); ........ console.log(...);
,注意添加 2x JSON.parse
)并执行该函数,以完全跳过网络。
好吧,这似乎可行,但是我没有从postsMeta.json
文件 IE 中看到 meta_value
:图像图像 url 来自 postsMeta
这是我需要的主要内容之一要在最后的transformedPosts
transformedPosts
似乎只是其中一个 json 文件,具体来说它是 posts.json
而不是两者的合并。
哦,你说得对,这是个bug,metaByPostId[post.post_id]
应该是metaByPostId[post.ID]
,去修复答案【参考方案4】:
直截了当地提出你的问题。我们希望:
将var a = /*some json*/
合并到var b = /*another json*/
修剪var exclusions = ["post_parent","meta_key"]
中的字段
合并 JSONS
首先,我们需要填充 a 和 b。 您的 JSON 可以使用 JSON.parse() 解析为 Javascript 对象:
let a = JSON.parse(/*JSON here*/);
let b = JSON.parse(/*JSON here*/);
因为 Javascript 中属性是如何定义的,如果你再次定义一个属性,第二个定义会覆盖第一个。您的 JSONS 仅包含作为键的字符串和作为值的字符串,因此 shallow copy 就足够了。 Object.assign() 会将所有属性(字段和值)复制到第一个参数中并返回最终对象。因此这会将 a 合并到 b 中,假设它们具有不同的键,否则 b 中的值将覆盖 a 中的值:
a = Object.assign(a,b);
否则,如果它们不是不相交的,则您必须定义一些关于如何加入的策略,例如可以优先考虑一个。下面,我们将值保留在 a 中:
a = Object.assign(b,a);
由于您提到了for
循环,下面的代码行与上面的两行代码相同,并且还可以向您展示如何编写自己的自定义 lambda 表达式的示例: p>
Object.keys(a).forEach(k=>b[k]=b[k]?b[k]:a[k]);
不想触摸a
和b
?创建第三个对象c
。
let c = Object.assign(,a,b)
最后(等到下面的修剪步骤完成)JSON.stringify() 会将您的合并对象转换回 JSON。
修剪排除项
在第三个示例之后,我们将c
与所有字段合并。
首先来自here的小技巧:
Object.filter = (obj, predicate) => Object.keys(obj)
.filter( key => predicate(obj[key]))
.reduce( (res, key) => (res[key] = obj[key], res), );
现在对象,就像数组有一个过滤器原型一样,具有扩展的对象原型。这并不是真正的最佳实践,因为这将扩展每个 Object,但是这个函数在 Javascript 的语义方面工作得很好,这个例子可以作为保持优雅 Javascript 样式代码的机会:
c = Object.filter(c, key=> !exclusions.includes(key) );
Voit-lá,完成。
对于定义的 Object.filter() 它使用 Array.filter() 和 Array.reduce() 。为了您的方便,请点击参考。
【讨论】:
在let a = JSON.parse(/*JSON here*/);
中,我们是放入json 文件的路径,如let a = JSON.parse(postmeta.json);
还是整个数组?
整个 JSON 作为字符串,在此处查看 w3schools.com/js/js_json_parse.asp 但您可以打开包含该字符串的文件。例如,如果您使用的是节点,则可以使用 fs w3schools.com/nodejs/nodejs_filesystem.asp
等等:var a = JSON.parse(fs.readFileSync(filepath));
(使用 NodeJS)
我在这里尝试你的代码glitch.com/edit/#!/tricky-rail我得到一个Unexpected token u in JSON at position 0
我的意思是,数组中的每一行都需要单独处理。首先用var strA =fs.readFileSync(filepath)
得到整个文件字符串,然后去掉开头的[,结尾的],然后用strA.split(",")得到JSON字符串数组。以上是关于合并从wordpress导出的两个Json文件的主要内容,如果未能解决你的问题,请参考以下文章
如何保持从 Blender 导出的 Three.js JSON 文件的向后兼容性
THREE.JS 从搅拌机中导出 JSON 模型(包括纹理)