Not able to convert keccak256 hash into a string type

Hi there does anyone how to cast a result of a keccak256/sha256, which returns a bytes32 into a string in Solidity? This doesn't seem to work in comparison to normal bytes32 objects and throws a failed to decode output error every time.

Here is the code below:

	function getHash(uint256 _id) external view returns (string memory) {
        return string(abi.encodePacked(keccak256(abi.encodePacked(_id, "value"))));
	}

The error:

	"error": "Failed to decode output: null: invalid codepoint at offset 0; 
unexpected continuation byte (argument=\"bytes\",
value=Uint8Array(0x8bb170e451ca7e22248c3383ea823c551dfb51469997174dd0ab7034be4877bb),
code=INVALID_ARGUMENT, version=strings/5.4.0)"

Found the solution, pass the result of the hash into this function toHex(bytes32 _hash)
Source: https://stackoverflow.com/questions/67893318/solidity-how-to-represent-bytes32-as-string

function toHex(bytes32 data) public pure returns (string memory) {
		return string(abi.encodePacked("0x", toHex16(bytes16(data)), toHex16(bytes16(data << 128))));
	}

	function toHex16(bytes16 data) internal pure returns (bytes32 result) {
		result =
			(bytes32(data) & 0xFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000) |
			((bytes32(data) & 0x0000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000) >> 64);
		result =
			(result & 0xFFFFFFFF000000000000000000000000FFFFFFFF000000000000000000000000) |
			((result & 0x00000000FFFFFFFF000000000000000000000000FFFFFFFF0000000000000000) >> 32);
		result =
			(result & 0xFFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000) |
			((result & 0x0000FFFF000000000000FFFF000000000000FFFF000000000000FFFF00000000) >> 16);
		result =
			(result & 0xFF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000) |
			((result & 0x00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000) >> 8);
		result =
			((result & 0xF000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000) >> 4) |
			((result & 0x0F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F00) >> 8);
		result = bytes32(
			0x3030303030303030303030303030303030303030303030303030303030303030 +
				uint256(result) +
				(((uint256(result) + 0x0606060606060606060606060606060606060606060606060606060606060606) >> 4) &
					0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F) *
				7
		);
	}

Note that OpenZeppelin Contracts includes a Strings.toHex utility function as well.

Right but that does not take a bytes as an input, only uint256 which is not what the result of a keccak256/sha256 returns.

You can try this:

function bytes32ToString(bytes32 _b) external pure returns (string memory) {
    return string(abi.encodePacked(_b));
}

This won't work for a result of a hashing function.

You're right. My bad!

For the record, it's still possible to use our library with bytes32 with a little workaround, by casting bytes32 to uint256:

Strings.toHexString(uint256(keccak256(...)), 32);