Объедините два файла Json, экспортированных из WordPress - PullRequest
0 голосов
/ 29 апреля 2018

У меня есть два файла Json, которые я экспортировал из WordPress и которые имеют соответствующие идентификаторы. Я хочу объединить их в один файл Json, чтобы я мог перенести его на веб-сайт, который я создаю с помощью Gatsby JS. Один из файлов - posts.json, а другой - postsMeta.json. Post_id в postsMeta соответствует идентификатору в Posts

Как мне лучше всего объединить их? Могу ли я запустить какой-то цикл for в js и как бы мне это сделать? Я нахожусь на Windows, есть ли какой-нибудь json explorer, который мог бы помочь мне сделать это.

наконец, я также хотел бы обрезать некоторые ненужные поля, такие как post_parent в posts json и что-то вроде meta_key в postsMeta 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"},

Обновление:

это является попыткой решить эту проблему с помощью текущего ответа, вы можете отредактировать код там.

Ответы [ 4 ]

0 голосов
/ 12 мая 2018

Тупо в точку вашего вопроса. Мы хотим:

  • объединить var a = {/*some json*/} в var b = {/*another json*/}
  • Обрезать поля в var exclusions = ["post_parent","meta_key"]

Объединить JSONS

Сначала нам нужно заполнить a и b. Ваши JSON-файлы можно разбирать на объекты Javascript с помощью JSON.parse () :

let a = JSON.parse(/*JSON here*/);
let b = JSON.parse(/*JSON here*/);

Поскольку, как свойства определяются в Javascript, если вы снова определите свойство, второе определение будет перезаписывать первое. Ваши JSONS содержат только строки в качестве ключей и строки в качестве значений, поэтому достаточно мелкой копии . Object.assign () скопирует все свойства (поля и значения) в первый аргумент и вернет конечный объект. Поэтому это объединит a в b, предполагая, что у них разные ключи, иначе значения в b перезапишут значения в a:

a = Object.assign(a,b);

В противном случае, если они не являются непересекающимися, вы должны определить некоторую политику в отношении того, как присоединиться, например, для приоритета. Ниже мы сохраняем значения вместо:

a = Object.assign(b,a);

Поскольку вы упомянули цикл for, строка ниже делает то же самое, что две строки кода выше , и также позволит вам показать пример того, как написать свое собственное лямбда-выражение:

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 со всеми полями.

Сначала небольшой взлом, взятый из здесь :

Object.filter = (obj, predicate) => Object.keys(obj)
    .filter( key => predicate(obj[key]))
    .reduce( (res, key) => (res[key] = obj[key], res), {} );

Теперь у объектов, как и у массивов, есть прототип фильтра, который расширил прототип объекта. На самом деле это не лучшая практика, так как это расширяет каждый объект, но эта функция работает довольно хорошо с учетом семантики Javascript, и этот пример дает возможность сохранить элегантный код стилей Javascript:

c = Object.filter(c, key=> !exclusions.includes(key) );

Войт-ла, готово.

Как и для определенного Object.filter (), он использует Array.filter () и Array.reduce () . Нажмите для справки, для вашего удобства.

0 голосов
/ 08 мая 2018

Как мне лучше всего объединить их?

Является ли обязательным для объединения двух файлов / данных 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"}];

Примеры: (см. эту скрипку для демонстрации)

// 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:

JSON.stringify( posts );

Но если вы на самом деле просто хотите что-то сделать с мета поста, вы можете перебрать объект posts и сделать это; e.g.:

// 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...
0 голосов
/ 08 мая 2018

Попробуйте этот фрагмент непосредственно в консоли 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);
  });
})();
  • замените URL-адреса соответственно, я использовал те из примера Glitch здесь
  • как прокомментировано, фактические данные скрыты в response[2].data. Используйте вкладку Сеть / Просмотр в разобранном виде, чтобы увидеть структуру
  • замените console.log на copy, если вы хотите, чтобы результат был скопирован в буфер обмена вместо записи в консоль
0 голосов
/ 29 апреля 2018

Если вы можете сделать это в 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,
}));

Я не люблю ручную настройку вещи на неопределенное - я думаю, что лучше явно сказать, какие реквизиты вы собираетесь включить, вместо загрузки всего и отмены определения определенных реквизитов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...