10985 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

Sous node.js je cherche à créer un calendrier et il s'agit ici de la gestion des fêtes fixes. Celles-ci sont définies dans des fichiers .json, mais ces fêtes (ou leur importance) peuvent changer selon les continents ou pays. Il y a donc un calendrier de référence, puis ensuite celui d'un continent (ici l'Europe) qui doit remplacer les infos précédentes, puis le calendrier d'un pays (ici la France), qui lui aussi doit remplacer les infos.

Exemple :

.json du calendrier général :
{
  "1402": {
    "name": "Saint Cyrille, moine et Saint Méthode, évêque",
    "color": "white",
    "grade": "3",
    "rank": "10"
  }
}


.json du calendrier européen :
{
  "1402": {
    "name": "Saint Cyrille, moine et Saint Méthode, évêque",
    "color": "white",
    "grade": "2",
    "rank": "8"
  }
}


.json du calendrier Français : pas de donnée sur cette fête.

On voit que le grade et le rank changent entre les deux .json pour le jour de Cyrille et Méthode : il passe de "mémoire obligatoire" (grade 3) à "fête" pour l'Europe (grade 2). Comme il n'y a pas de données pour le calendrier français on doit en rester au grade 2.

Donc, en considération de cela j'appelle plusieurs .json avec le module fs de node.js et j'inclue chacun dans une variable. Or je m'y prends mal car seul le dernier .json est effectif, les deux premiers sont écrasés dans la variable 'data' :
const fs = require('fs'),
      general = './data/json/generalRomanCalendar.json',
      european = './data/json/europeanRomanCalendar.json',
      french = './data/json/frenchRomanCalendar.json',
      { DateTime } = require('luxon')

const liturgicalCalendar = date => {
  const data1 = JSON.parse(fs.readFileSync(general, 'utf8')),
        data2 = JSON.parse(fs.readFileSync(european, 'utf8')),
        data3 = JSON.parse(fs.readFileSync(french, 'utf8')),
        dt = DateTime.local(),
        currentYear = dt.toFormat('yyyy'),
        currentDayMonth = dt.toFormat('ddMM'),
        ge = easter.gregorianEaster(currentYear),
        easterDate = DateTime.local(ge.year, ge.month, ge.day)

  // Gestion des fêtes votives
  if (typeof date === 'undefined') date = currentDayMonth
  let data = data1[date] // le problème est ici
  data = data2[date]     // le problème est ici
  data = data3[date]     // le problème est ici

console.log(data.grade) // pas de donné au lieu de '3'
console.log(data.rank) // pas de donné au lieu de '8'

// -> le reste du code...
}

Comment appeler mes .json pour que les infos soient remplacées ? Par exemple ici je voudrais que le 'data.grade' dans cette circonstance soit à '2'.

PS : je me suis trompé, il fallait que je mette ce sujet dans la catégorie "côté serveur".
PS2 : finalement non : la solution montrera qu'il s'agit avant tout d'une problématique js.
Modifié par Olivier C (28 Oct 2020 - 07:00)
Modérateur
Bonjour,

La ligne suivante doit faire une erreur, puisque data3 normalement ne contient rien.
data = data3[date]

Essaie de le retirer dans un premier temps, et regarde si ça marche mieux.
Si c'est bien ça, alors, il faut tester si data3 est bien un objet, et éventuellement si data3[ data ] contient bien des données, genre :
if (typeof data3 === 'object') {
    if(data3[date]) {data = data3[date];}
}

Avant ça, il faudrait aussi sans doute tester data1 et data2 au cas où (sauf si t'es sûr que les fichiers sources existent bien). Et aussi tester ce que renvoie tes fs.readFileSync() avant de faire des JSON.parse().

Amicalement,
Modifié par parsimonhi (27 Oct 2020 - 11:03)
Merci pour ton intervention Parcimonhi.

Je suis sûr que les fichiers sont appelés car je les ai tous testé individuellement. C'est l'articulation entre les 3 qui me pose problème.

Tel que j'ai créé le code j'efface la valeur des données des deux précédents avec le dernier .json pour la variable data. Je ne peu donc pas écraser mon data.grade par l'appel d'un fichier suivant par exemple, il faut forcément faire des tests pour remplacer chaque valeur si présente ? Je ne sais pas si je sais bien m'expliquer...
Modérateur
Bonjour,

Ton code actuel efface les valeurs précédentes (monde et europe) par des données qui n'existent pas.

EDIT: donc, oui, faut tester pour n'effacer les valeurs précédentes que si une nouvelle valeur est effectivement disponible.

Amicalement,
Modifié par parsimonhi (27 Oct 2020 - 13:03)
Modérateur
Bonjour,

Ton code actuel efface les valeurs précédentes (monde et europe) par des données qui n'existent pas.

EDIT: donc, oui, faut tester pour n'effacer les valeurs précédentes que si une nouvelle valeur est effectivement disponible.

EDIT2: remplace
data = data3[date]

par
if (typeof data3 === 'object') {
    if(data3[date]) {data = data3[date];}
}

et reviens dire si ça a marché ou pas.

Amicalement,
Meilleure solution
Magnifique ! Ta solution est la bonne :
  let data = data1[date]
  if ((typeof data2 === 'object') && (data2[date])) data = data2[date]
  if ((typeof data3 === 'object') && (data3[date])) data = data3[date]

console.log(data)
/* Retourne le bon résultat :
 * {
 *   name: 'Saint Cyrille, moine et Saint Méthode, évêque',
 *   color: 'white',
 *   grade: '2',
 *   rank: '8'
 * }
 */

Sujet résolu. Je te remercie chaleureusement.
Modifié par Olivier C (27 Oct 2020 - 23:05)
Ah énorme ! Quand on commence à creuser on finit par trouver. J'ai trouvé une méthode avec un résultat équivalent au précédent mais plus spécifiquement dédié à cette utilisation (du coup on peut utiliser 'const' à la place de 'let') :
// ES9 :
const data = {...data1[date], ...data2[date], ...data3[date]}

Notez que l'on pourrait aussi procéder avec Object.assign pour obtenir ce résultat (et aussi pour plus de compatibilité) :
// // ES6 :
const data = Object.assign(data1[date], data2[date], data3[date])

Mais comme le dit la fonction il y a aussi réassignation du tableau cible (qui est le premier de la liste), c'est donc moins propre.

Ah là là ! Quand on sait enfin ce que l'on doit chercher : j'ai tapé "javascript fusionner objets" dans Google...

J'ai écris ce dernier post pour laisser une trace sur ce forum, ce qui n'enlève rien à la valeur de l'aide de Parcimonhi. Merci encore à toi.
Modifié par Olivier C (28 Oct 2020 - 12:12)