-1

I have the JSON like this:

{
    "class": {
        "type": "major",
        "order": "1"
    },
    "number": {
       "type": "date",
       "order": "5"
    },
    "amount": {
        "type": "date",
        "order": "3"
    },
}

I need to make that into PHP array and sort based on order field.

If the number is same then the order should stay as it is.

EDIT:

Also if some of the elements don't have order then they should come at bottom

TN888
  • 7,659
  • 9
  • 48
  • 84
user3147180
  • 923
  • 3
  • 12
  • 25

2 Answers2

4

You can use json_decode() to convert it to a PHP array. You'll then need to write a stable implementation of usort() to sort the values. Something like this:

function stableSort(array $array) {
    // turn the input array into something we can more easily manipulate
    $lookup = array();
    $i = 0;
    foreach($array as $key => $value) {
        $lookup[] = array(
                'position' => $i++,
                'key' => $key,
                'value' => $value);
    }

    usort($lookup, function(array $a, array $b) {
        if(!isset($a['value']['order'])) {
            if(!isset($b['value']['order'])) {
                return $a['position'] > $b['position'];
            }
            return 1;
        }

        if(!isset($b['value']['order'])) {
            return -1;
        }

        if($a['value']['order'] == $b['value']['order']) {
            return $a['position'] > $b['position'];
        }

        return $a['value']['order'] > $b['value']['order'] ? 1 : -1;
    });

    // recreate the original array
    $sorted = array();
    foreach($lookup as $element) {
        $sorted[$element['key']] = $element['value'];
    }

    return $sorted;
}

$array = json_decode($json, true);
$sorted = stableSort($array);

We never return 0 from within the comparison function, as that would break the guarantee of a stable sort. The first two if statements exist to handle the cases where the order key does not exist in one or both of the inputs.

George Brighton
  • 5,131
  • 9
  • 27
  • 36
0

you should decode json to array, and then use usort to sort array:

$data = '{
    "class": {
        "type": "major",
        "order": "1"
    },
    "number": {
       "type": "date",
       "order": "5"
    },
    "amount": {
        "type": "date",
        "order": "3"
    }
}';

$array = json_decode($data, true);
usort($array, function ($left, $right) {
  if ($left['order'] == $right['order']) {
    return 0;
  }
  return $left['order'] < $right['order'] ? -1 : 1;
});

var_dump($array);

To guarantee stable sort, you need to index elements before sorting, and use that index while comparing "equal" elements. I also add some conditions to move elements with empty order to bottom (but with preserving change of it primary sequence):

$i = 0;
foreach ($array as $key => $value) {
  $array[$key]['original_order'] = $i;
  $i++;
}

uasort($array, function ($left, $right) {
  if (isset($left['order'])) {
    if(isset($right['order'])) {
      if ($right['order'] == $left['order']) {
        return $left['original_order'] < $right['original_order'] ? -1 : 1;
      }
      return $left['order'] < $right['order'] ? -1 : 1;
    }
    return -1;
  } elseif(isset($right['order'])) {
    return 1;
  } else {
    return $left['original_order'] < $right['original_order'] ? -1 : 1;
  }
});

foreach ($array as $key => $value) {
  unset($array[$key]['original_order']);
}
ziollek
  • 1,973
  • 1
  • 12
  • 10