我有两个JSON文件,我从wordpress导出,有相应的ID我希望将它们组合成一个Json文件,所以我可以把它带到我用Gatsby JS构建的网站。其中一个文件是posts.json
,另一个是postsMeta.json
。 postsMeta 中的post_id与帖子中的ID
我最好如何合并两者?我可以在js中运行某种for
循环吗?我怎么会这样?我在窗户上有一些可以帮助我做这件事的json探险家。
最后,我还想删除帖子 json中的post_parent
等一些不必要的错误,以及 postsMeta <中的meta_key
之类的内容。 / em> json。
好的,希望这很清楚,先谢谢。
以下是两个文件中第一个对象对应的示例
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尝试使用当前答案解决此问题,您可以在那里编辑代码。
答案 0 :(得分:6)
我最好如何合并两者?
强制性是否合并了两个JSON文件/数据?
因为您可以从脚本中请求或加载JSON数据(或者甚至将它们放在HTML
中),然后获取特定元字段/键的元值,这个{{1}能做到这一点:
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()
示例:(有关演示,请参阅this Fiddle)
// 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"}];
但如果您真的必须合并JSON数据,您可以:(再次参见the same 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数据:
// 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.stringify( posts );
对象并做事; e.g:
posts
答案 1 :(得分:5)
如果你能在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,
}));
我不爱手动设置未定义的东西 - 我认为明确说出你要包含的道具更好,而不是加载所有东西并取消定义某些道具。
答案 2 :(得分:5)
直接在Chrome DevTools控制台中试用此代码段:
(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);
});
})();
response[2].data
中。使用网络选项卡/解析视图查看结构console.log
替换为copy
,如果您希望将结果复制到剪贴板,而不是记录到控制台答案 3 :(得分:2)
直截了当地提出你的问题。我们想:
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()会将所有属性(字段和值)复制到第一个参数中并返回最终的Object。因此,假设它们具有不同的键,这将合并为b,否则b中的值将覆盖a中的值:
a = Object.assign(a,b);
否则,如果它们不是不相交的,则必须定义一些关于如何加入的策略,例如可以优先考虑一个。下面,我们将值保留在:
a = Object.assign(b,a);
由于您提到了for
循环,下面的行与上面的两个代码行相同,并且还允许向您展示如何编写自己的自定义lambda表达式的示例:
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), {} );
Now Objects,就像数组有一个过滤器原型一样,具有扩展的Object原型。这不是真正的最佳实践,因为这会扩展每个Object,但是这个函数非常适合于Javascript的语义,这个例子可以保留优雅的Javascript样式代码:
c = Object.filter(c, key=> !exclusions.includes(key) );
Voit-lá,完成。
对于定义的Object.filter(),它使用Array.filter()和Array.reduce()。为方便起见,请点击以供参考。